django-admin-dependent-autocomplete
django-admin-dependent-autocomplete adds a single capability to Django
Admin's built-in autocomplete: a ForeignKey autocomplete can be constrained
by another ForeignKey in the same admin form.
It deliberately reuses Django Admin's autocomplete_fields, Select2 bundle,
AutocompleteJsonView, permissions, search_fields, pagination, and JSON
format. It does not introduce a second autocomplete implementation or any
runtime dependency besides Django.
Install
pip install django-admin-dependent-autocomplete
Add django_admin_dependent_autocomplete to INSTALLED_APPS so Django can
discover its static JavaScript file.
Simple shorthand dependency
from django.contrib import admin
from django_admin_dependent_autocomplete.admin import DependentAutocompleteAdminMixin
from .models import Address, City, Country
@admin.register(Country)
class CountryAdmin(admin.ModelAdmin):
search_fields = ["name"]
@admin.register(City)
class CityAdmin(admin.ModelAdmin):
# Required by Django Admin's native autocomplete.
search_fields = ["name"]
@admin.register(Address)
class AddressAdmin(DependentAutocompleteAdminMixin, admin.ModelAdmin):
autocomplete_fields = ["city"]
autocomplete_dependencies = {
"city": "country",
}
For the configuration above, Address.city is the autocomplete child and
Address.country is its parent. The related City model must have a
country ForeignKey to the same model. The autocomplete results are then
equivalent to:
City.objects.filter(country_id=selected_country_id)
search_fields on the target model's ModelAdmin is required by Django
Admin for every field listed in autocomplete_fields.
Target fields with a different name
The short form above uses country both as the parent field on Address and
as the ForeignKey on City. When those names differ, configure the target
model field explicitly:
autocomplete_dependencies = {
"city": {
"depends_on": "selected_country",
"lookup": "country",
},
}
Here selected_country is the field on the source admin form and country
is the ForeignKey on the target autocomplete model. Both names are checked
server-side; the browser only ever supplies the selected parent primary key.
The package installs a small per-admin URL that delegates to Django's native
autocomplete view. It applies the configured parent filter before invoking the
related model admin's get_search_results(). Permissions, search_fields,
custom get_search_results(), limit choices, pagination, and the native JSON
response remain in use. The browser only sends a parent value; it never sends
a lookup name, and the relationship is validated server-side from the mapping.
Changing a parent clears its dependent child. Existing values on a change form are left intact until the parent changes. When the parent is empty, its dependent autocomplete returns no results.
Chained dependencies
Each mapping can use an explicit target lookup, so source form fields do not need to share names with the target model relationships. For example, a Country → District → City chain can use intentionally different source names:
class AddressAdmin(DependentAutocompleteAdminMixin, admin.ModelAdmin):
autocomplete_fields = ["selected_district", "selected_city"]
autocomplete_dependencies = {
"selected_district": {
"depends_on": "selected_country",
"lookup": "country",
},
"selected_city": {
"depends_on": "selected_district",
"lookup": "district",
},
}
Here Address.selected_country, selected_district, and selected_city are
the form fields, while District.country and City.district are the target
model ForeignKey fields. Changing a country clears its district and city;
changing a district clears its city. Saved values remain visible on change
forms until the user changes an ancestor field.
Mixing with a project ModelAdmin
Put DependentAutocompleteAdminMixin before your ModelAdmin subclass:
class AddressAdmin(DependentAutocompleteAdminMixin, ProjectModelAdmin):
autocomplete_fields = ["city"]
autocomplete_dependencies = {"city": "country"}
The mixin uses cooperative super() for formfield_for_foreignkey(),
get_urls(), and check(). A custom formfield_for_foreignkey() further
down the MRO can still explicitly provide a widget; in that case it takes
precedence. Existing get_form() implementations are unaffected.
Current limits
Version 0.1 supports one ForeignKey parent and one ForeignKey autocomplete
child per mapping entry. It does not support many-to-many fields, non-admin
forms, generic foreign keys, arbitrary callbacks, or multiple parents for one
child. Multiple entries can form chained dependencies. Inline formsets receive
the JavaScript behavior when added, but they are not a separately expanded API
surface yet.
Compared with django-autocomplete-light
django-autocomplete-light is a full-featured autocomplete framework. This package intentionally does much less: it extends Django Admin's built-in autocomplete with dependent field filtering.
Compatibility
The package requires Python 3.8+ and supports Django 3.2, 4.2, 5.0, 5.1, and 5.2. CI covers those Django release lines, including Python 3.8 with Django 3.2. Django is the only runtime dependency.
Run the included test app
python -m venv .venv
source .venv/bin/activate
pip install -e ".[dev]"
python testapp/manage.py migrate
python testapp/manage.py createsuperuser
python testapp/manage.py seed_data
python testapp/manage.py runserver
Open /admin/testapp/address/add/. Select Paraguay, then a district (Capital
or Central), then a city. Select Argentina to see its districts and cities.
Changing the country clears both dependent fields; changing a district clears
its city. Reopen a saved address to verify the selected district and city stay
visible.
Development checks
pytest
ruff check .
python -m build
twine check dist/*
To run the oldest supported environment locally, install the development
dependencies with Python 3.8 and Django 3.2, then run pytest again.
Roadmap
Possible future additions include multiple parent dependencies, more relation types, and a documented inline-specific API, without changing the simple mapping used in v0.1.
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
Filter files by name, interpreter, ABI, and platform.
If you're not sure about the file name format, learn more about wheel file names.
Copy a direct link to the current filters
File details
Details for the file django_admin_dependent_autocomplete-0.1.0.tar.gz.
File metadata
- Download URL: django_admin_dependent_autocomplete-0.1.0.tar.gz
- Upload date:
- Size: 13.6 kB
- Tags: Source
- Uploaded using Trusted Publishing? Yes
- Uploaded via:
twine/7.0.0 CPython/3.13.14
File hashes
| Algorithm | Hash digest | |
|---|---|---|
| SHA256 |
e07676a4428365cbe5943cc5a1c9d10e803d05e9376f25dc2e95b6ab2b326fea
|
|
| MD5 |
8fbd14cad3068f28cc9018b02be4343c
|
|
| BLAKE2b-256 |
3aeb2d64bd9410f993102c8eae660c731021499f391cc337a3eefd866a13cab7
|
Provenance
The following attestation bundles were made for django_admin_dependent_autocomplete-0.1.0.tar.gz:
Publisher:
release.yml on JuanBer90/django-admin-dependent-autocomplete
-
Statement:
-
Statement type:
https://in-toto.io/Statement/v1 -
Predicate type:
https://docs.pypi.org/attestations/publish/v1 -
Subject name:
django_admin_dependent_autocomplete-0.1.0.tar.gz -
Subject digest:
e07676a4428365cbe5943cc5a1c9d10e803d05e9376f25dc2e95b6ab2b326fea - Sigstore transparency entry: 2568433735
- Sigstore integration time:
-
Permalink:
JuanBer90/django-admin-dependent-autocomplete@8871de59d42eeed2b81fde7816513c958a2198ff -
Branch / Tag:
refs/tags/v0.1.0 - Owner: https://github.com/JuanBer90
-
Access:
public
-
Token Issuer:
https://token.actions.githubusercontent.com -
Runner Environment:
github-hosted -
Publication workflow:
release.yml@8871de59d42eeed2b81fde7816513c958a2198ff -
Trigger Event:
push
-
Statement type:
File details
Details for the file django_admin_dependent_autocomplete-0.1.0-py3-none-any.whl.
File metadata
- Download URL: django_admin_dependent_autocomplete-0.1.0-py3-none-any.whl
- Upload date:
- Size: 10.3 kB
- Tags: Python 3
- Uploaded using Trusted Publishing? Yes
- Uploaded via:
twine/7.0.0 CPython/3.13.14
File hashes
| Algorithm | Hash digest | |
|---|---|---|
| SHA256 |
0952f2df52f3c0068c7e285d176eb7969a9ae28502370392a16c8ccbd360d589
|
|
| MD5 |
57e9708854d5a803ddd8f0c01166be9b
|
|
| BLAKE2b-256 |
8c172d5cbb6d300fa93add4806410ee094ba6733649f0efe0a095a74a1940ecb
|
Provenance
The following attestation bundles were made for django_admin_dependent_autocomplete-0.1.0-py3-none-any.whl:
Publisher:
release.yml on JuanBer90/django-admin-dependent-autocomplete
-
Statement:
-
Statement type:
https://in-toto.io/Statement/v1 -
Predicate type:
https://docs.pypi.org/attestations/publish/v1 -
Subject name:
django_admin_dependent_autocomplete-0.1.0-py3-none-any.whl -
Subject digest:
0952f2df52f3c0068c7e285d176eb7969a9ae28502370392a16c8ccbd360d589 - Sigstore transparency entry: 2568433740
- Sigstore integration time:
-
Permalink:
JuanBer90/django-admin-dependent-autocomplete@8871de59d42eeed2b81fde7816513c958a2198ff -
Branch / Tag:
refs/tags/v0.1.0 - Owner: https://github.com/JuanBer90
-
Access:
public
-
Token Issuer:
https://token.actions.githubusercontent.com -
Runner Environment:
github-hosted -
Publication workflow:
release.yml@8871de59d42eeed2b81fde7816513c958a2198ff -
Trigger Event:
push
-
Statement type: