URL Auto-Registration
Developer guide for the Enezaframework. Part of the Developer documentation.
Table of Contents
- Overview
@auto_url_registerget_registered_urls- Writing the App's
urls.py - Generated URL Reference
- Naming and Collisions
- Change History
- Related Guides
Overview
Instead of hand-writing a URL pattern for every CRUD view, decorate the view with
@auto_url_register. The decorator records the view in a registry, and the app's urls.py pulls the
generated patterns with get_registered_urls(app_name).
sequenceDiagram
participant Dev as Developer
participant Dec as auto_url_register
participant Reg as URL_REGISTRY
participant URLS as app urls.py
participant Django
Dev->>Dec: decorate view class
Dec->>Reg: append view class
URLS->>Reg: get_registered_urls(app_name)
Reg-->>URLS: list of path() patterns
URLS->>Django: urlpatterns = [*dynamic_urls]
Django-->>Dev: reverse("app:model_list") works@auto_url_register
Import and apply it to each view class:
from enezaframework.utils import auto_url_register
from enezaframework.views import BaseListView, BaseDetailView, BaseCreateView, BaseDeleteView
from accountpayable.models import VendorTable
@auto_url_register
class VendorTableListView(BaseListView):
model = VendorTable
def set_list_fields(self):
return ["vendorno", "searchname"]
def set_search_fields(self):
return ["vendorno", "searchname"]
@auto_url_register
class VendorTableDetailView(BaseDetailView):
model = VendorTable
@auto_url_register
class VendorTableCreateView(BaseCreateView):
model = VendorTable
@auto_url_register
class VendorTableDeleteView(BaseDeleteView):
model = VendorTable
Rules and behavior:
- Model-backed views must define a
modelattribute, otherwise the decorator raisesValueError. PureViewsubclasses (such asBaseAction) are exempt. - The decorator appends the class to
URL_REGISTRY; it does not create URLs by itself. - The view must expose the
view_typeattribute expected byget_registered_urls(the base views set this for you:list,detail,create,delete,action,parameter,one_to_one_detail,autocomplete,workflow,document_report). url_nameoverrides the URL prefix; otherwise the lowercase model name (model._meta.model_name) is used.
get_registered_urls
from enezaframework.utils import get_registered_urls
dynamic_urls = get_registered_urls("accountpayable")
Signature: get_registered_urls(app_name="enezaframework").
The function iterates URL_REGISTRY, keeps classes whose module belongs to app_name, and produces a
path() for each recognized view_type. Views from other apps are skipped, so each app only receives
its own routes. Views whose model is not a Django Model subclass are skipped as well.
Writing the App's urls.py
Combine manually defined views with the framework-generated routes.
from django.urls import path
from . import views
from enezaframework.utils import get_registered_urls
app_name = "accountpayable"
dynamic_urls = get_registered_urls(app_name)
urlpatterns = [
# Manually defined views (dashboards, reports, custom endpoints)
path("dashboard", views.accountpayable_dashboard, name="accountpayable_dashboard"),
# All auto-registered CRUD routes for this app
*dynamic_urls,
]
- Set
app_nameto the actual app name; it namespaces reverse lookups. - Distribute
*dynamic_urlsintourlpatterns; if you forget, the app will miss every auto-generated CRUD endpoint. - Manually defined views are still needed for things the framework does not generate (dashboards, custom reports).
Generated URL Reference
Route shape and URL name depend on the view's view_type. The prefix is url_name if set, otherwise the
lowercase model name.
view_type |
Pattern | URL name |
|---|---|---|
list |
{prefix}/ |
{prefix}_list |
detail |
{prefix}/<str:pk>/ |
{prefix}_detail |
create |
{prefix}_create/ |
{prefix}_create |
delete |
{prefix}_delete/<str:pk>/ |
{prefix}_delete |
parameter |
{prefix}/ |
{prefix}_parameter |
one_to_one_detail |
{prefix}/<str:pk>/ |
{prefix}_detail |
action |
{Action Name Title}/<str:pk> |
{action_name}_action |
dashboard |
{prefix}/ |
{prefix}_dashboard |
autocomplete |
{prefix}_autocomplete/ |
{prefix}_autocomplete |
workflow |
{prefix}_workflow/<str:pk>/ |
{prefix}_workflow |
document_report |
{report_name}_report/<str:pk>/ |
{report_name}_report |
Notes:
- Primary keys are captured as
<str:pk>because framework models use UUID primary keys. - There is no auto-generated
updateroute. Editing is handled by the detail view; use the detail URL for edit navigation. document_reportusesreport_namewhen set, otherwise the model prefix.
Example for a VendorTable model
| URL name | Path |
|---|---|
accountpayable:vendortable_list |
/vendortable/ |
accountpayable:vendortable_detail |
/vendortable/<pk>/ |
accountpayable:vendortable_create |
/vendortable_create/ |
accountpayable:vendortable_delete |
/vendortable_delete/<pk>/ |
If the view sets url_name = "vendors", the prefixes become /vendors/, /vendors/<pk>/,
/vendors_create/, and /vendors_delete/<pk>/, with URL names vendors_list, and so on.
Naming and Collisions
- Two views with the same
view_typeand the same prefix in one app produce colliding URL names. Seturl_nameon one of them to disambiguate. - The prefix for an unset
url_nameis the model name, not the class name. AVendorTableListViewandVendorTableDetailViewtherefore share thevendortableprefix but differ by suffix. - Menu entries must reference the exact generated name (
app_name:url_name); see Menu & Navigation Configuration. report_nameon a document report view lets one model expose multiple distinct report URLs.
The user is solely responsible for testing and validating routing; the developer/agent does not run the application.
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-07-10 | 0.2.16 | Custom url_name added on UrlMixin and non-UrlMixin views, decoupling URL names from model names. |
| 2026-07-11 | 0.2.17 | get_registered_urls() fixed to honour url_name across all URL pattern types (previously always used the model name). |