Party-Bridge Pattern
Developer guide for the Enezaframework party system. Part of the Party System series.
Table of Contents
- Overview
- When You Need a Bridge
- Auto-Detection
- What the Bridge Does Automatically
- Minimal Inline View
- Request Flow
- Related Guides
Overview
The party inline system uses shared views whose parent_model is Party. For backward compatibility or custom one-to-one inline views, you may instead declare an inline view whose parent_model is your party-based model (for example Customer). BaseInlineOneToOneDetailView bridges that gap: it walks parent → parent.party → profile and resolves the object correctly without any override.
When You Need a Bridge
Use BaseInlineOneToOneDetailView with a bridge when:
- You are adding a custom one-to-one inline (a profile extension, a preferences row) keyed off the party.
- You have an existing inline view whose
parent_modelis the business model and you do not want to repoint it atParty. - You need the inline's
related_nameto be the FK/O2O from the inline model to the party (for exampleperson_profile).
If you are happy with the framework's shared party inlines, you do not need any of this — see Party Inline System.
Auto-Detection
BaseInlineOneToOneDetailView._is_party_bridge() (enezaframework/views/baseinline.py:652-666) returns True only when both conditions hold:
- The inline model (e.g.,
Person) has apartyfield (FK or OneToOne) pointing atParty. - The parent model (e.g.,
Customer) has apartyFK pointing atParty.
flowchart TD
START[Inline view resolves object] --> M{"model has<br/>party -> Party?"}
M -->|No| NORMAL[Use standard related_name resolution]
M -->|Yes| P{"parent_model has<br/>party -> Party?"}
P -->|No| NORMAL
P -->|Yes| BRIDGE["Party bridge active<br/>field = 'party'"]What the Bridge Does Automatically
When a bridge is detected, the base class:
find_field_by_related_name()→ returns'party'(baseinline.py:668-671).get_object()→ resolves the instance viaparent_instance.party→model.objects.get(party=...), or by the URLpkif present (baseinline.py:673-684).form_valid()→ setsform.instance.party = parent_instance.partybefore saving (baseinline.py:686-693).
def get_object(self, queryset=None):
if self._is_party_bridge():
pk = self.kwargs.get('pk')
if pk:
return get_object_or_404(self.model, pk=pk)
main_object_pk = self.request.GET.get('main_object_pk')
if main_object_pk:
parent_instance = get_object_or_404(self.parent_model, pk=main_object_pk)
if parent_instance.party:
return get_object_or_404(self.model, party=parent_instance.party)
raise Http404
return super().get_object(queryset)
Minimal Inline View
No find_field_by_related_name(), get_object(), or form_valid() overrides are needed.
from enezaframework.views import BaseInlineOneToOneDetailView
from enezaframework.utils import auto_url_register
from enezacommon.models import Person
from myapp.models import Customer
@auto_url_register
class CustomerPersonInlineDetailView(BaseInlineOneToOneDetailView):
model = Person
parent_model = Customer
related_name = 'person_profile'
def detail_ui_view(self):
return [
{
'name': 'Personal Information',
'icon': 'Home',
'Fieldcolumns': [
{'fields': ['first_name', 'middle_name', 'last_name']},
{'fields': ['birthday', 'email']},
],
},
]
related_name must match the reverse accessor from the inline model to the party — for Person it is person_profile; for Business it is business_profile.
Request Flow
sequenceDiagram
participant Parent as Customer detail page
participant Inline as CustomerPersonInlineDetailView
participant Bridge as _is_party_bridge
participant DB as Database
Parent->>Inline: GET with main_object_pk=customer_pk
Inline->>Bridge: check model.party and parent.party
Bridge-->>Inline: True
Inline->>DB: Customer.objects.get(pk=main_object_pk)
DB-->>Inline: customer
Inline->>DB: Person.objects.get(party=customer.party)
DB-->>Inline: person
Inline-->>Parent: inline form partial
Parent->>Inline: POST with main_object_pk=customer_pk
Inline->>Bridge: check bridge
Inline->>DB: person = form.save(commit=False)
Inline->>DB: form.instance.party = customer.party
Inline->>DB: save
Inline-->>Parent: updated inline partial