Party System Quick Start
Developer guide for the Enezaframework party system. Part of the Party System series.
Table of Contents
- Overview
- Step 1 — Define the Model
- Step 2 — Re-export the Model
- Step 3 — Define the CRUD Views
- Step 4 — Register URLs
- Step 5 — Add the Menu Entry
- Step 6 — Migrate
- What the Detail Page Shows
- Related Guides
Overview
A party-based entity needs the same pieces as any CRUD feature, plus the PartyModelMixin base class. The framework supplies the rest: party creation, profile creation, and the detail-page inlines.
You will build: a Customer model with a party type, standard list/detail/create/delete views, a URL namespace, and a menu entry — with party data handled automatically.
flowchart LR
M[1. Model<br/>PartyModelMixin] --> R[2. Re-export<br/>models/__init__.py]
R --> V[3. CRUD views<br/>detail_ui_view]
V --> U[4. URLs<br/>auto_url_register]
U --> N[5. Menu<br/>apps.py]
N --> G[6. Migrate]
G --> D[Working party-based pages]Step 1 — Define the Model
# myapp/models/customer.py
from django.db import models
from enezaframework.models import EnezaMaster, PartyModelMixin
from enezacommon.models.choices import PartyCategory
class Customer(PartyModelMixin, EnezaMaster):
customer_no = models.CharField(
max_length=50,
verbose_name="Customer No.",
)
customer_type = models.CharField(
max_length=5,
choices=PartyCategory.choices,
verbose_name="Customer Type",
)
name = models.CharField(
max_length=255,
verbose_name="Name",
)
email = models.CharField(
max_length=255,
blank=True,
null=True,
verbose_name="Email",
)
sequence_field_name = 'customer_no'
document_name = 'CUSTOMER'
@property
def party_category(self):
return self.customer_type
def get_party_defaults(self):
defaults = super().get_party_defaults()
defaults['display_name'] = self.name or self.customer_no or 'Customer'
return defaults
def __str__(self):
if self.party and self.party.display_name:
return self.party.display_name
return self.customer_no or ''
class Meta:
db_table = 'customer'
verbose_name = "Customer"
verbose_name_plural = "Customers"
Details of the mixin contract are in PartyModelMixin & Model Integration.
Step 2 — Re-export the Model
# myapp/models/__init__.py
from .customer import Customer
Without this re-export, from myapp.models import Customer fails. See Standardized App Structure.
Step 3 — Define the CRUD Views
# myapp/views/customer_views.py
from enezaframework.views import (
BaseListView, BaseDetailView, BaseCreateView, BaseDeleteView,
)
from enezaframework.utils import auto_url_register
from myapp.models import Customer
@auto_url_register
class CustomerListView(BaseListView):
model = Customer
def set_list_fields(self):
return ['customer_no', 'party', 'customer_type', 'name']
def set_search_fields(self):
return ['customer_no', 'name']
@auto_url_register
class CustomerDetailView(BaseDetailView):
model = Customer
def detail_ui_view(self):
return [
{
'name': 'Basic Information',
'icon': 'Home',
'Fieldcolumns': [
{'fields': ['customer_no', 'customer_type']},
{'fields': ['name', 'email']},
],
},
]
@auto_url_register
class CustomerCreateView(BaseCreateView):
model = Customer
def detail_ui_view(self):
return [
{
'name': 'Basic Information',
'icon': 'Home',
'Fieldcolumns': [
{'fields': ['customer_no', 'customer_type']},
{'fields': ['name', 'email']},
],
},
]
@auto_url_register
class CustomerDeleteView(BaseDeleteView):
model = Customer
Do not add
'party'toFieldcolumns. It is auto-hidden from forms, and the party inlines are injected separately. See Party View Layer.
Step 4 — Register URLs
# myapp/urls.py
from django.urls import path
from . import views # noqa: F401 (imports the view modules / re-exports)
from enezaframework.utils import get_registered_urls
app_name = "myapp"
dynamic_urls = get_registered_urls(app_name)
urlpatterns = [
*dynamic_urls,
]
This yields the standard names (myapp:customer_list, myapp:customer_detail, myapp:customer_create, myapp:customer_delete). See URL Auto-Registration.
Step 5 — Add the Menu Entry
# myapp/apps.py
from django.apps import AppConfig
from enezaframework.utils import load_icon
class MyappConfig(AppConfig):
default_auto_field = "django.db.models.BigAutoField"
name = "myapp"
menus = [
{
"fasttab": "my_masterdata",
"name": "Master Data",
"icon": load_icon("users_icon"),
"menuitems": [
{
"url": f"{name}:customer_list",
"name": "Customers",
"icon": load_icon("users_icon"),
},
],
},
]
See Menu & Navigation Configuration.
Step 6 — Migrate
python manage.py makemigrations myapp
python manage.py migrate
Django adds the party_id column automatically because the mixin contributes the field. For converting an existing model, follow Party System Migration instead.
What the Detail Page Shows
After saving the first record, the party and its profile exist, and the detail page shows the party inlines without any view override.
sequenceDiagram
actor U as User
participant D as CustomerDetailView
participant B as BaseDetailView
participant P as Party inlines
U->>D: GET /customer/{pk}/
D->>B: get_context_data()
B->>B: party_object = object.party
B->>B: inject Address + ContactInformation + Person/Business
B-->>D: fieldtabs + inline_related_object + party_object
D-->>U: detail page with party inline tabs
U->>P: HTMX loads an inline (main_object_pk = party.pk)
P-->>U: inline partial| Party type | Inlines shown |
|---|---|
PRS |
Address, Contact Information, Personal Details |
ORG |
Address, Contact Information, Business Details |