Add simple dynamic interaction to the otherwise static django admin.
Project description
django-dynamic-admin-forms
Add simple interactions to the otherwise static django admin.
Installation
-
Install the package via pip:
pip install django-dynamic-admin-forms
or via pipenv:
pipenv install django-dynamic-admin-forms
-
Add the module to
INSTALLED_APPS
:INSTALLED_APPS = ( ..., 'dynamic_admin_forms', 'django.contrib.admin' ... )
Ensure that the
dynamic_admin_forms
comes before the defaultdjango.contrib.admin
in the list of installed apps, because otherwise the templates, which are overwritten bydynamic_admin_forms
won't be found. -
Ensure that the
dynamic_admin_forms
templates are found via usingAPP_DIRS
setting:TEMPLATES = [ { 'BACKEND': 'django.template.backends.django.DjangoTemplates', 'APP_DIRS': True, ... }, ]
-
Run
python manage.py collectstatic
to include this apps Javascript code in yoursettings.STATIC_ROOT
directory
Usage
-
Add the
dynamic_admin_forms.DynamicModelAdminMixin
to your admin classes -
In addition to the standard
fields
declaration, specify a list ofdynamic_fields
-
For each dynamic field, add a method
get_dynamic_{field_name}_field
to the admin- Input:
data: Dict[str, Any]
- the cleaned form data - Output:
queryset: Optional[Queryset]
- The values to select fromvalue: Any
- The value, the field should have (must be compatible to the field type)hidden: Bool
- True, if field should be hidden
- Input:
-
A rather non-sensical example:
from django.contrib import admin from .models import MyModel from dynamic_admin_forms.admin import DynamicModelAdminMixin @admin.register(MyModel) class MyModelAdmin(DynamicModelAdminMixin, admin.ModelAdmin): fields = ("name", "city") dynamic_fields = ("city",) def get_dynamic_city_field(self, data): # automatically choose first city that matches first letter of name name = data.get("name") if not name: queryset = City.objects.all() value = data.get("city") else: queryset = City.objects.filter(name__startswith=name[0]) value = queryset.first() hidden = not queryset.exists() return queryset, value, hidden
How it works
Whenever a dynamic form changes, an event handler makes a request to a special endpoint, which returns new HTML to swap
into the existing form. This new HTML is directly generated by django.contrib.admin
, so we only have to set the
outerHTML of the correct HTML elements to update the form.
Limitations
- does not work in conjunction with inlines
- does not validate that the selected value is really part of the original queryset
- if anybody can modify your DOM, they could potentially inject invalid values
- you have to write
Model.clean()
methods to guard against that
- only tested with Django 3.2
Changelog
- 0.1.0: Initial release
- 0.1.1: README fixes
- 0.1.2: README fixes
- 0.1.3: Change Demo-GIF hosting
- 0.1.4: README fixes
Project details
Release history Release notifications | RSS feed
Download files
Download the file for your platform. If you're not sure which to choose, learn more about installing packages.
Source Distribution
Built Distribution
Hashes for django-dynamic-admin-forms-0.1.4.tar.gz
Algorithm | Hash digest | |
---|---|---|
SHA256 | 624e81578ff08f7de04b9bb0a02d4f0094213c72d1213d6566b65815012bc17c |
|
MD5 | b8eb00187e824fb7483bcd0693f860cd |
|
BLAKE2b-256 | 364b79eae7bee6e37906bc5448d41b6b6b7e03081fa695ced0dcc22be5f61e78 |
Hashes for django_dynamic_admin_forms-0.1.4-py2.py3-none-any.whl
Algorithm | Hash digest | |
---|---|---|
SHA256 | fc62d652f4bfc6bf75e2a00d789dabc5bff749b3dfa59f2d11d3c3b5f1a80a52 |
|
MD5 | 2ee290ff371448ba6bf952b5ae63291b |
|
BLAKE2b-256 | 1b3908b393f0a95d96e7a5ca279eed8cd90e0aa360b51ebb227c4694e46ed169 |