Standardized App Structure

Developer guide for the Enezaframework. Part of the Developer documentation.

Table of Contents

  1. Why a Standard Structure
  2. Directory Layout
  3. The models/ Package
  4. The views/ Package
  5. Templates
  6. Migrations
  7. Requirements Docs
  8. App Configuration
  9. Change History
  10. Related Guides

Why a Standard Structure

Every business-logic app follows the same layout so that tooling, the CLI, and human developers can predict where things live. Enezaframework reads models and views through package __init__ re-exports, so following the import conventions is not optional — it is what makes from accountpayable.models import VendorTable work.


Directory Layout

eneza startapp creates this scaffold with empty models/, views/ and migrations/ packages. Each package contains only __init__.py; no sample model, sample view or sample menu item is generated. Add model and view files as the app grows, then re-export them from the package __init__.py.

A typical app looks like this:

text
accountpayable/
├── __init__.py
├── admin.py
├── apps.py                 # App config + navigation menus
├── models/                 # One file per model
│   ├── __init__.py         # Re-exports every model
│   ├── vendortable.py
│   └── vendortabledetails.py
├── views/                  # One file per view group
│   ├── __init__.py         # Re-exports every view
│   └── vendorviews.py
├── templates/              # Only when generic templates are insufficient
│   └── accountpayable/
├── requirements/           # PRD.md and other specifications
├── urls.py                 # Aggregates auto-registered URLs
└── migrations/
    └── __init__.py
flowchart TD
    APP[accountpayable app]
    APP --> APPSPY[apps.py<br/>config + menus]
    APP --> MODELS[models package]
    APP --> VIEWS[views package]
    APP --> URLS[urls.py]
    APP --> MIG[migrations]
    APP --> TMPL[templates optional]
    APP --> REQ[requirements docs]

    MODELS --> M1[vendortable.py]
    MODELS --> M2[vendortabledetails.py]
    MODELS --> MINIT[__init__.py re-exports]

    VIEWS --> V1[vendorviews.py]
    VIEWS --> VINIT[__init__.py re-exports]

The models/ Package

  • Put each model in its own file, for example models/customertable.py and models/vendortable.py.
  • models/__init__.py must import every model from its file so callers can do a single import.
python
# accountpayable/models/__init__.py
from .vendortable import VendorTable
from .vendortabledetails import VendorTableDetails
from .vendorpostinggroup import VendorPostingGroup
from .vendorgroup import VendorGroup

With that in place, other modules can import cleanly:

python
from accountpayable.models import VendorTable, VendorTableDetails

The framework itself follows the same pattern. See enezaframework/models/__init__.py for the canonical example. Because of that file, from enezaframework.models import EnezaMaster, EnezaDocument works, while a class that is not re-exported there is not importable from the package root (for example EnezaMasterDetail).

Models should inherit from an Enezaframework base model rather than models.Model directly whenever they participate in the standard CRUD/multi-tenant behavior. See Base Models & Model Types.


The views/ Package

  • Put a view or a closely related set of views in its own file, for example views/customerviews.py and views/vendorviews.py.
  • views/__init__.py must import those views so URL generation and cross-imports resolve.
python
# accountpayable/views/__init__.py
from .vendorviews import *

Then the app's urls.py can do from . import views and reference views.cashandbankdashboard for manually defined views.

Each framework view should be decorated with @auto_url_register; see URL Auto-Registration.


Templates

Most apps do not need their own templates. Enezaframework ships generic list, detail, and form templates that the base views reuse.

  • Only create a custom template when there is a presentation requirement the generic templates cannot satisfy.
  • App-specific templates live under a subdirectory named after the app, for example templates/accountpayable/.
  • Reuse the base HTML design and static assets described in Frontend Templates & UI Reuse.

Migrations

Standard Django migrations manage schema changes for the app's models.

bash
python manage.py makemigrations accountpayable
python manage.py migrate

Keep the standard migrations/__init__.py in place.


Requirements Docs

The requirements/ folder holds the app's Product Requirement Documents (PRD.md) and other specifications. Use it to document why the app exists, its entities, and its business rules, so future work has a written reference.


App Configuration

The app's apps.py holds the AppConfig. It also declares navigation metadata and the menus list that the sidebar renders. Menu metadata (menu_verbose_name, app_entry_menu, app_icon, menu_position) is read from every installed AppConfig by enezaframework/context_processors.py.

A CLI-scaffolded app starts with menus = [] and an app_entry_menu that resolves to the dashboard module entry. The app appears in the module menu, but its fast tabs stay empty until views and menu items are added.

python
from django.apps import AppConfig


class AccountpayableConfig(AppConfig):
    default_auto_field = "django.db.models.BigAutoField"
    name = "accountpayable"
    menu_verbose_name = "Accounts Payable"
    app_entry_menu = "accountpayable:vendortable_list"
    app_icon = "building-library"
    menu_position = 30

See Menu & Navigation Configuration for the full menus structure.


Change History

Dated changes that affect this guide, taken from docs/Release note/CHANGELOG.md and the release notes. For the complete history, see the changelog.

Date Version What changed
2026-06-27 — New inline_details_partial.html and inline_update_partial.html partials added under the framework's core/partials/.
2026-08-23 0.2.19 New enezaagents app added to INSTALLED_APPS — an additional example of the standard app layout.
2026-10-31 0.2.22 eneza startapp now creates empty models/, views/ and migrations/ packages with no sample model, view or menu item; menus starts empty and the app uses the dashboard entry empty state.

No dated changes to the app directory layout or the models/ and views/ re-export rules appear in the changelog for the 0.2.7–0.2.19 window.