Standardized App Structure
Developer guide for the Enezaframework. Part of the Developer documentation.
Table of Contents
- Why a Standard Structure
- Directory Layout
- The
models/Package - The
views/Package - Templates
- Migrations
- Requirements Docs
- App Configuration
- Change History
- 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:
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.pyandmodels/vendortable.py. models/__init__.pymust import every model from its file so callers can do a single import.
# 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:
from accountpayable.models import VendorTable, VendorTableDetails
The framework itself follows the same pattern. See
enezaframework/models/__init__.pyfor the canonical example. Because of that file,from enezaframework.models import EnezaMaster, EnezaDocumentworks, while a class that is not re-exported there is not importable from the package root (for exampleEnezaMasterDetail).
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.pyandviews/vendorviews.py. views/__init__.pymust import those views so URL generation and cross-imports resolve.
# 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.
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.
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.