Published on Feb. 24, 2025
Go homeDjango view dispatching
When developing Django applications, you often need views that handle multiple related actions on the same resource. Traditional approaches might lead to bloated views or unnecessary duplication across multiple view classes.
In this post, I'll share a practical pattern for organizing and dispatching different actions within a single Django view based on my experience building complex applications.
Let's consider a common scenario, managing a contact record that requires multiple operations:
- Updating basic contact details (name, email, phone)
- Managing company relationships for the contact
We can model the actions above using an enum.
class ContactSectionEnum(enum.StrEnum):
"""Models the contact sections."""
DETAIL = enum.auto()
COMPANIES = enum.auto()
We can then organise the view code around this enum.
- Render only the required section
- Apply only the required action
In order to achieve this we can use query params for dispatching within our view code.
class ContactManage(View):
def get_section(self, request: HttpRequest) -> ContactSectionEnum:
"""Parse the section from the request query params."""
section = ContactSectionEnum.DETAIL # Use DETAIL as the default section
section_raw = request.GET.get("s", "")
if section_raw:
try:
section = ContactSectionEnum(section_raw)
except:
pass
return section
def get(self, request: HttpRequest, contact_id: int) -> HttpResponse:
section = self.get_section(request=request)
contact = get_object_or_404(db_models.Contact.objects.filter(pk=contact_id))
if section is ContactSectionEnum.DETAIL:
section_context = self.get_detail_context_data(contact_id=contact_id, contact=contact)
elif section is ContactSectionEnum.COMPANIES:
section_context = self.get_companies_context_data(contact_id=contact_id, contact=contact)
else:
raise ValueError(f"Invalid section {section}")
context = self.get_context_data(contact_id=contact_id, contact=contact)
context =| section_context
return render(request, "contact_manage.html", context)
def post(self, request: HttpRequest, contact_id: int) -> HttpResponse:
section = self.get_section(request=request)
contact = get_object_or_404(db_models.Contact.objects.filter(pk=contact_id))
if section is ContactSectionEnum.DETAIL:
return self.process_update_detail(request=request, contact_id=contact_id, contact=contact)
elif section is ContactSectionEnum.COMPANIES:
return self.process_update_companies(request=request, contact_id=contact_id, contact=contact)
else:
raise ValueError(f"Invalid section {section}")
def process_update_detail(self, request: HttpRequest, contact_id: int, contact: db_models.Contact) -> HttpResponse: ...
def process_update_companies(self, request: HttpRequest, contact_id: int, contact: db_models.Contact) -> HttpResponse: ...