Skip to main content

Django Router

You have a data and you need to provide some CRUD functionality for it quickly. What do you do?

  1. Create model
  2. Add some views
  3. ????
  4. PROFIT!

Right? Right! Done! And nothing works! Why? URLS.PY!!! You always forget this ones? I have a solution!

Maintaining Django's urls.py can become really annoying when you have a lot of apps with dozens urls in each. Other frameworks deal with it in elegant ways, like Flask's @app.route decorator. This project brings same concept to Django by adding @router decorator functions.

Compatibility

This project is automatically tested with Python 3.7, 3.8, 3.9, 3.10 and Django 2.2, 3.1, 3.2, 4.0, 4.1. Latest version for each release. Compatibility with earlier versions of Python or Django(starting from 2.0) is possible, but not guaranteed.

Installation

Package is hosted in pypi.org thus you can use any tool that works with it to install the package:

pip install django-router

poetry add django-router

Add django_router to your INSTALLED_APPS

# superduperproject/settings.py
INSTALLED_APPS = [
    ...
    "django_router",
    ...
]

Modify project urls.py (the top one)

# superduperproject/urls.py
from django_router import router

# the only time you need to modify any `urls.py`
urlpatterns = router.urlpatterns

# or with existing ones
urlpatterns = [
    ...
] + router.urlpatterns

Concept

To easily understand all the auto naming concept of the app take a look at testing project within the repo.

Usage

Just use decorator in your apps' views.py. Django Router uses autodiscovery feature, so make sure views you're interested in are either inside views.py or get imported into it.

# employees/views.py
from django_router import router
from employees.models import Employee
from django.shortcuts import render
from django.views.generic.edit import CreateView

# Works with function based views
# Resulting url will be `/employees/employee_list/`
@router.path()
def employee_list(request):
    employees = Employee.objects.all()
    return render(request, 'employee_list.html', {'employees':employees})

# As well as with class based views
# Resulting url will be `/employees/employee_create/`
@router.path()
def EmployeeCreate(CreateView):
    model = Employee

And that's it! No more need to deal with lengthy urls.py!

How it works

Router has two functions path and re_path which work exactly the same as django.urls functions you already know. Except that you don't even need to specify url or name.

View module path is used to determine the resulting URL prefix. So URL for views in employees/views.py app will start with /employees/... , employees/manage/views.py - /employees/manage/... URL etc.

Also first module will be used as a namespace for reverse

reverse('employees:employee_list')

NOTICE: nested namespaces are not supported for now.

App has some functionality builtin for automatic pattern and name generation.

For FBVs if no name is provided function name will be used, camel case will be turned into snake case:

# same as path('import_employees/', import_employees, name='import_employees')
@router.path()
def import_employees(request):
    ...

# same as path('import_employees/', ImportEmployees.as_view(), name='import_employees')
@router.path()
class ImportEmployees(View):
    ...

For generic Django views(CreateView,UpdateView,ListView,DetailView,DeleteView) there's some builtin autonaming behavior which tries to be logical.

@route.path()
class NewEmployeeView(CreateView):
    model = Employee

# is same as
path('employee/create/', NewEmployeeView.as_view(), name='employee_create')

Of course you can specify path and name as usual:

@router.path('im_emp/', name='employees_import')
def import_employees(request):
    ...

Settings

Settings for the project are mostly to control autonaming behavior. These are default settings for the project

ROUTER_SETTINGS = {
    "SIMPLE_AUTO_NAMING": False,
    "WORDS_SEPARATOR": "_",
    "MODEL_NAMES_MONOLITHIC": True,
    "DJANGO_ADMIN_LIKE_NAMES": False,
    "MODULE_PATH_MAP": False
}

SIMPLE_AUTO_NAMING: if set to true all other settings are ignored, name and url are composed from view name, CamelCase turned to snake_case:

"test_app.views.SimpleCbv" -> ["/test_app/simple_cbv/", "test_app:simple_cbv"],
"test_app.views.simple_fbv" -> ["/test_app/simple_fbv/", "test_app:simple_fbv"],

WORDS_SEPARATOR: a separator char that'll be used during camel to snake case conversion in view names:

@router.path()
class EmployeeList(ListView):
    model = Employee

WORDS_SEPARATOR = "_"

path('employee_list/', EmployeeList.as_view(), name='employee_list')

WORDS_SEPARATOR = "-"

path('employee_list/', EmployeeList.as_view(), name='employee-list')


MODEL_NAMES_MONOLITHIC: only works when MODEL_BASED_PATTERNS = True, control whether separator is used for model names consisting of multiple words

@router.path()
class EmployeeAddressList(ListView):
    model = EmployeeAddress

MODEL_NAMES_MONOLITHIC = True

path('employeeaddress/', EmployeesAddressList.as_view(), name='employeeaddress_list')

MODEL_NAMES_MONOLITHIC = False

path('employee_address/', EmployeesAddressList.as_view(), name='employee_address_list')


DJANGO_ADMIN_LIKE_NAMES: if true uses strings like in Django admin for view names and paths

  • ListView: changelist
  • UpdateView: change
  • CreateView: add
@router.path()
class EmployeeCreate(CreateView):
    model = Employee

path('employee/add/', EmployeeCreate.as_view(), name='employee_add')


MODULE_PATH_MAP: By default router uses view module path to generate resulting url: students.views.StudentUpdate is split into three parts:

  • students: top level app name, will be used as a prefix for all views inside student.views
  • views: name of the module containing views, skipped during path name generation
  • StudentList: view name, turned into a last part of the url depending on previous settings So resulting url for the view may look like this /students/<int:pk>/update/

However you may have a view that has following module path: companies.departments.views.DepartmentUpdate, by default resulting url will look like this: /companies/departments/<int:pk>/update/ If you want to avoid this and skip everything between app name and last module name set this settings to False.

Management commands

python manage.py router_list - to see list of all available routes created by the router.

python manage.py router_urls - to see list of all available routes as if they're in urls.py

Metadata

Release files for django-router 1.0.8

For a detailed explanation of source distributions (sdists) and built distributions (wheels), please see the package formats documentation.

Source distribution (sdist)

Source distribution for django-router 1.0.8
File Size Uploaded Provenance
django_router-1.0.8.tar.gz 8.6 kB Without provenance Details

Built distribution (wheel)

Table of built distributions (wheels) for django-router 1.0.8
File Interpreter ABI Platform
django_router-1.0.8-py3-none-any.whl Python 3 none any Details

Total release size: 17.4 kB

Release files / django_router-1.0.8.tar.gz

Download URL django_router-1.0.8.tar.gz
Size 8.6 kB
Tags Source
SHA-256 checksum
How to use checksums
6c9675f37c0eee70c02fc42c4260eb0b13c4940c6a331a83a7f184dbe3dbab57
BLAKE2b-256 checksum
How to use checksums
523684583092f29c5df50418a4587698ee81687b06c1dee5e5f1118785199771
Upload date
Uploaded using Trusted Publishing?
What is trusted publishing?
Yes
Uploaded via pdm/2.15.0 CPython/3.10.12 Linux/6.5.0-1018-azure

Release files / django_router-1.0.8-py3-none-any.whl

Download URL django_router-1.0.8-py3-none-any.whl
Size 8.8 kB
Tags Python 3
SHA-256 checksum
How to use checksums
aaea5aa938488475dacca271a87d13f77012ca097c75530c0f42eea1234b73f6
BLAKE2b-256 checksum
How to use checksums
3a76f6224baf68959fd5bbe1ce849c6dd4a9576e3016fed18c156179c2066af5
Upload date
Uploaded using Trusted Publishing?
What is trusted publishing?
Yes
Uploaded via pdm/2.15.0 CPython/3.10.12 Linux/6.5.0-1018-azure

Security for django-router 1.0.8

Provenance

Provenance describes where a file came from. On PyPI, provenance is shared via attestations, which provide a verifiable record of the build or publishing details. View details, limitations and caveats.

No provenance found

None of the files in this release were uploaded with provenance metadata.

A note on package security

PyPI is a repository for distributing packages, not a service for auditing them. While third-party security researchers and our staff do their best to detect and remove malicious packages, PyPI cannot guarantee the quality, security or suitability of any given package.

Anthropic, PBC Visionary sponsor Bloomberg Visionary sponsor Hudson River Trading Visionary sponsor Meta Visionary sponsor NVIDIA Visionary sponsor Microsoft Sustainability sponsor Depot Continuous Integration AWS Cloud computing and Security Sponsor Datadog Monitoring Fastly CDN Google Download Analytics Sentry Error logging StatusPage Status page