Customizing Vaccination Admin View
In this video, we are going to customize the admin panel for vaccination related views. We will create some custom templates and some custom action buttons right in our django admin panel.
Resources
Admin
So, open the admin.py of vaccination and here we will created a custom vaccination admin.
class CustomVaccinationAdmin(admin.ModelAdmin):
# At first, lets specify the list display.
# [Register this admin and explain the changes line by line]
list_display = ["patient", "campaign", "slot", "is_vaccinated"]
# Now, lets add a search field
search_fields = ["patient__first_name", "patient__middle_name", "patient__last_name"]
# After that, let us implement the list filter
list_filter = ["is_vaccinated"]
# Now, for the detailview, let us specify the readonly_fields.
readonly_fields = [
"patient",
"campaign",
"is_vaccinated",
"updated_by",
"updated_on",
"date",
]
# Now, lets register this custom admin panel for our vaccination model.
admin.site.register(Vaccination, CustomVaccinationAdmin)
Template
Now, I want to add a custom buttons in our detail view of vaccination. These buttons will be an option to approve vaccination of patient, downloading the appointment letter and vaccination certificate.
To implement this feature, we have to add a template in the detailview of vaccination. So, in the customvaccinationadmin, add a field named change_form_template.
change_form_template = "admin/change-vaccination.html"
Now, create this "change-vaccination.html" template in vaccination/templates/admin.
I have attached change-vaccination.html file in the resources section. Please download it and paste the content in this html file.
{% extends 'admin/change_form.html' %}
{% block submit_buttons_bottom %}
{% if original %}
<div class="submit-row">
{% if not original.is_vaccinated %}
<a href="#" style="margin-right: 20px;" target="_blank">Approve Vaccination</a>
{% endif %}
<a href="#" style="margin-right: 20px;" target="_blank">Appointment Letter</a>
<a href="#" style="margin-right: 20px;" target="_blank">Vaccination Certificate</a>
</div>
{% endif %}
{{ block.super }}
{% endblock %}
[Explain the template]
Views
Now, we have to create a view to approve the vaccination from our django admin panel. For this, open views.py of vaccination.
from django.contrib import messages
from django.core.exceptions import PermissionDenied
from django.urls import reverse
from django.http import HttpResponseRedirect
# Here, create a view named approve_vaccination.
# This function based view takes vaccination_id in the parameter.
@login_required
def approve_vaccination(request, vaccination_id):
# At first, we will check whether the user has permission to change_vaccination or not.
if request.user.has_perm("vaccination.change_vaccination"):
# Now, in the try except block, we will query the vaccination object of the patient.
try:
vaccination = Vaccination.objects.get(id=vaccination_id)
except Vaccination.DoesNotExist:
return HttpResponseBadRequest("object not found with given id")
# After that, we will check, whether the currently logged in admin user is in the list of agents of that vaccination campaign or not.
if request.user in vaccination.campaign.agents.all():
# If the admin user is in the agents of that vaccination campaign, we will approve the vaccination of that patient.
# Here, we will check whether the patient is already vaccination or not.
if vaccination.is_vaccinated:
# If the patient is already vaccinated we will show a message and then redirect the user to vaccination detail page.
messages.info(request, "Vaccination is already Approved")
return HttpResponseRedirect(reverse("vaccination:vaccination-detail", kwargs={"pk": vaccination_id}))
else:
# If the patient is not vaccination, we have to set the is_vaccination value to True
vaccination.is_vaccinated = True
vaccination.date = timezone.now().date()
vaccination.updated_by = request.user
vaccination.save()
messages.success(request, "Vaccination approved successfully")
return HttpResponseRedirect(reverse("vaccination:vaccination-detail", kwargs={"pk": vaccination_id}))
else:
# If the admin user not in the agents of vaccination campaign, then raise a permission denied exception.
messages.error(request, "You are not assigned to approve this vaccination")
raise PermissionDenied()
else:
# If the user doesn't have permission to change the vaccination object, then raise the permission denied exception.
messages.error(request, "You don't have permission to approve vaccination")
raise PermissionDenied()
Now, create a urls path to access this view.
path("approve-vaccination/<int:vaccination_id>/", views.approve_vaccination, name="approve-vaccination"),
Then, update the urls in change-vaccination.html
<div class="submit-row">
{% if not original.is_vaccinated %}
<a href={% url 'vaccination:approve-vaccination' original.id %} style="margin-right: 20px;" target="_blank">Approve Vaccination</a>
{% endif %}
<a href={% url 'vaccination:appointment-letter' original.id %} style="margin-right: 20px;" target="_blank">Appointment Letter</a>
<a href={% url 'vaccination:vaccination-certificate' original.id %} style="margin-right: 20px;" target="_blank">Vaccination Certificate</a>
</div>
[Run the development server and see the changes.]
Template Enhancements
At last, lets try to update some links in our dashbord page. I just forget to update these links.
So, open the base.html file
{% if request.user.is_authenticated %}
<li class="nav-item">
<a class="nav-link" href="{% url 'accounts:logout' %}"><i class="fas fa-sign-in-alt"></i> Logout</a>
</li>
{% else %}
<li class="nav-item">
<a class="nav-link" href="{% url 'accounts:login' %}"><i class="fas fa-sign-in-alt"></i> Login</a>
</li>
<li class="nav-item">
<a class="nav-link" href="{% url 'accounts:signup' %}"><i class="fas fa-plus"></i> Signup</a>
</li>
{% endif %}
[Run the development server and see the changes.]
[Commit the changes and push it in the remote repository.]