Party View Layer

Developer guide for the Enezaframework party system. Part of the Party System series.

Table of Contents

  1. Overview
  2. What You Do Need to Define
  3. What You Do Not Need to Define
  4. What You May Optionally Define
  5. Adding Your Own Inlines Alongside Party Inlines
  6. Responsibility Split
  7. Related Guides

Overview

A party-based model uses the standard CRUD base views. The presence of PartyModelMixin changes nothing about how the views are declared; it only changes what the detail view injects into the page at runtime.

The rule of thumb: declare the same views you would for any other model, and delete any party-specific code you used to write.


What You Do Need to Define

View Base class Required members
List BaseListView model, set_list_fields(), set_search_fields()
Detail BaseDetailView model, detail_ui_view()
Create BaseCreateView model, detail_ui_view()
Delete BaseDeleteView model
python
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

What You Do Not Need to Define

Do not write any of the following for a party-based model — the framework already does it:

  • get_inline_related_objects() — BaseDetailView auto-injects the party inlines (enezaframework/views/base.py:290-294).
  • get_related_object_id() — InlineMixin resolves the profile IDs through the party chain (enezaframework/views/mixins.py:894-927).
  • Any logic to create or link the Party — the post_save signal owns it.
  • A form field for party — UiMixin.get_form_class() excludes it (enezaframework/views/mixins.py:353-361).
flowchart TD
    subgraph You["You write"]
        LV[List view + fields]
        DV[Detail view + detail_ui_view]
        CV[Create view + detail_ui_view]
        DEL[Delete view]
    end
    subgraph Framework["Framework provides"]
        P1[party FK field]
        P2[Party auto-creation]
        P3[Person/Business profile]
        P4[Party inlines on detail]
        P5[party hidden from forms]
        P6[Profile id resolution]
    end
    LV --> P4
    DV --> P4
    DV --> P6
    CV --> P5

What You May Optionally Define

  • Additional non-party inlines. Override get_inline_related_objects(), call super() to keep the party inlines, then append your own. See the next section.
  • Custom one-to-one inline views. If you need your own profile inline view instead of the shared party views, use BaseInlineOneToOneDetailView and let the party bridge resolve it. See Party-Bridge Pattern.
  • Inline detail views for Person/Business. Useful for backward compatibility with pre-existing URLs.

Adding Your Own Inlines Alongside Party Inlines

The base get_inline_related_objects() returns the party inlines. To add regular child inlines without losing them, extend the returned list:

python
@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']},
                ],
            },
        ]

    def get_inline_related_objects(self):
        inlines = super().get_inline_related_objects()
        inlines.append(
            {
                'name': 'salesorders',
                'caption': 'Sales Orders',
                'active': 1,
                'relation_name': 'sales_orders',
                'position': 2,
                'icon': 'DocumentPlus',
                'model': 'SalesOrder',
                'app': 'myapp',
            }
        )
        return inlines

Always call super() first; hard-coding the list replaces the party inlines and silently breaks the party tabs.

See Field & Inline UI Configuration for the full inline dictionary schema.


Responsibility Split

Task You Framework
Declare the model and fields Yes —
Provide party_category / get_party_defaults() Yes —
List/detail/create/delete views Yes —
Party FK field — Yes
Party + profile creation — Yes
Party inlines and their IDs — Yes
Hide party from forms — Yes
Extra app-specific inlines Optional —