CRUD Base Views

Developer guide for the Enezaframework. Part of the architecture series.

Table of Contents

  1. Overview
  2. View Inheritance
  3. BaseListView
  4. BaseDetailView
  5. BaseCreateView
  6. BaseDeleteView
  7. BaseParameter
  8. BaseAction
  9. Related Guides

Overview

Enezaframework ships class-based views that implement common CRUD behavior and reuse generic templates. A child view normally only sets model and a few configuration methods. Every view should be decorated with @auto_url_register so its URLs are generated automatically.

sequenceDiagram
    participant Browser
    participant URL as urls.py
    participant View as BaseListView
    participant Model as Model
    participant Tmpl as Generic template

    Browser->>URL: GET /accountpayable/vendortable/
    URL->>View: dispatch()
    View->>View: set_list_fields()
    View->>View: set_search_fields()
    View->>Model: get_queryset()
    Model-->>View: queryset
    View->>Tmpl: render(context with fields + rows)
    Tmpl-->>Browser: HTML list page

View Inheritance

classDiagram
    class BaseListView
    class BaseDetailView
    class BaseCreateView
    class BaseDeleteView
    class BaseParameter
    class BaseAction

    BaseListView --|> ListView
    BaseDetailView --|> DetailView
    BaseCreateView --|> CreateView
    BaseDeleteView --|> DeleteView
    BaseParameter --|> DetailView
    BaseAction --|> View

Concrete framework subclasses (BaseSetupsDetailView, BaseSourceDocumentDetailView, BaseJournalsDetailView, and so on) extend these core views; see Inline & Specialized Views.


BaseListView

Displays a list of records.

  • Template: generic list template supplied by Enezaframework; children usually do not set template_name.
  • Requires: model, and a set_list_fields method.
  • Search: set_search_fields is also required by the base class. Return an empty list when no search is needed.
python
from enezaframework.views import BaseListView
from enezaframework.utils import auto_url_register
from accountpayable.models import VendorTable


@auto_url_register
class VendorTableListView(BaseListView):
    model = VendorTable

    def set_list_fields(self):
        list_fields = ["vendorno", "searchname", "vendortype", "vendorgroup", "blocked"]
        return list_fields

    def set_search_fields(self):
        search_fields = ["vendorno", "searchname"]
        return search_fields

set_list_fields and set_search_fields raise NotImplementedError in the base view if not overridden (enezaframework/views/base.py). Implement both; return [] from set_search_fields to disable searching.


BaseDetailView

Displays a single record and handles editing (GET and POST).

  • Template: generic detail/form template supplied by Enezaframework.
  • Requires: model and a detail_ui_view method describing the tab/column layout.
  • Inlines: implement get_inline_related_objects to show related objects as inline tabs.
  • One-to-one resolution: override get_related_object_id when a one-to-one inline must be resolved (for example through a generic/ContentType relationship). Match the signature used by the base inline class on your branch.
  • Actions: define action_list to expose action buttons.
python
from enezaframework.views import BaseDetailView
from enezaframework.utils import auto_url_register
from accountpayable.models import VendorTable


@auto_url_register
class VendorTableDetailView(BaseDetailView):
    model = VendorTable

    action_list = [
        {
            "name": "Print Name",
            "icon": "DocumentPlus",
            "url": "printname",
            "confirm_message": "Are you sure you want to print this name?",
        },
    ]

    def detail_ui_view(self):
        Fieldtabs = [
            {
                "name": "Basic Information",
                "icon": "Home",
                "disable_fields": ["vendorno", "blocked", "vendortype"],
                "Fieldcolumns": [
                    {"fields": ["vendorno", "searchname", "vendorgroup"]},
                    {"fields": ["vendortype", "blocked"]},
                ],
            },
        ]
        return Fieldtabs

The full layout schema — disable_fields, disable_if, headerpostion, and extended ManyToMany configuration — is documented in Field & Inline UI Configuration.


BaseCreateView

Creates a new record and reuses the same generic form template as BaseDetailView.

  • Requires: model and a detail_ui_view method.
  • Fields listed in disable_fields are typically server-generated or read-only during creation.
python
from enezaframework.views import BaseCreateView
from enezaframework.utils import auto_url_register
from accountpayable.models import VendorTable


@auto_url_register
class VendorTableCreateView(BaseCreateView):
    model = VendorTable

    def detail_ui_view(self):
        Fieldtabs = [
            {
                "name": "Basic Information",
                "icon": "Home",
                "disable_fields": ["vendorno"],
                "Fieldcolumns": [
                    {"fields": ["searchname", "vendorgroup", "vendortype"]},
                    {"fields": ["blocked"]},
                ],
            },
        ]
        return Fieldtabs

Inlines are usually not shown until the parent record exists. Either create the parent first, or load inlines via HTMX after the initial save.


BaseDeleteView

Deletes a record after a confirmation page.

python
from enezaframework.views import BaseDeleteView
from enezaframework.utils import auto_url_register
from accountpayable.models import VendorTable


@auto_url_register
class VendorTableDeleteView(BaseDeleteView):
    model = VendorTable

The framework handles the success redirect.


BaseParameter

A specialized view for a model that has a single instance (or one instance per entity), such as application parameters.

  • class BaseParameter(UiMixin, InlineMixin, DetailView).
  • Expected attributes: model and a detail_ui_view method.
  • You typically do not create separate list/detail/create views for such a model; the parameter view both displays and updates it.
python
from enezaframework.views import BaseParameter
from enezaframework.utils import auto_url_register
from accountpayable.models import PayablesSetup


@auto_url_register
class PayablesSetupView(BaseParameter):
    model = PayablesSetup

    def detail_ui_view(self):
        Fieldtabs = [
            {
                "name": "General",
                "icon": "Home",
                "Fieldcolumns": [
                    {"fields": ["default_vendor_group", "payment_terms"]},
                ],
            },
        ]
        return Fieldtabs

BaseAction

A view that performs a custom action on a model instance. Actions appear as buttons or menu items on list/detail views.

  • class BaseAction(View).
  • Requires: model, action_name, and a process_action(self, pk) implementation.
  • action_name drives the generated URL name ({action_name}_action). url_name and view_type = "action" are also part of the contract.
  • The base post() reads the pk, calls process_action, then redirects to the record's detail view.
python
from enezaframework.views import BaseAction
from enezaframework.utils import auto_url_register


@auto_url_register
class PrintNameAction(BaseAction):
    model = VendorTable
    action_name = "printname"

    def process_action(self, pk):
        vendor = self.model.objects.get(pk=pk)
        # ... business logic ...
        return vendor

Reference the action from a detail view's action_list (see BaseDetailView above). The url value is a partial identifier; the framework builds the full app_name:... URL name.