原理是通过更改模板中的js,然后使用ajax异步获取选项。
1、首先找到模板change_form.html并复制到templates中
2、然后找到要更改的字段id,手动F12查找
3、然后更改模板,添加js代码(注意放在endblock前)
以下为新增代码
<script type="text/javascript">
document.addEventListener('DOMContentLoaded', function () {
const sheSelect = document.getElementById('id_shen');
const shiSelect = document.getElementById('id_locity');
const quSelect = document.getElementById('id_dist');
function addEmptyOption(selectElement) {
//设置默认空选项
const emptyOption = document.createElement('option');
emptyOption.value = '';
emptyOption.text = '---------';
selectElement.add(emptyOption, 0);
}
function resetSelect(selectElement) {
//清空所有选项并设置为空
selectElement.length = 0;
addEmptyOption(selectElement);
};
// addEmptyOption(shiSelect);
// addEmptyOption(quSelect);
sheSelect.addEventListener('change', function () {
const shenId = this.value;
// provinceSelect.length = 0;
resetSelect(shiSelect);
resetSelect(quSelect);
if (!shenId) {
return;
}
const url = '/api/ZZZZ/'+shenId
fetch(url)
.then(response => response.json())
.then(data => {
for (const key in data) {
const option = document.createElement('option');
option.value = key;
option.text = data[key];
shiSelect.add(option);
}
});
});
shiSelect.addEventListener('change', function () {
const shiId = this.value;
resetSelect(quSelect);
if (!shiId) {
return;
}
const url = '/api/XXXX/'+shiId
fetch(url)
.then(response => response.json())
.then(data => {
for (const key in data) {
const option = document.createElement('option');
option.value = key;
option.text = data[key];
quSelect.add(option);
}
});
});
});
</script>
这里要注意admin.py 中有联动的字段不能在 autocomplete_fields 中,不然会无效。
PS:以下为gpt参考资料,经测试可用:
在Django admin后台实现三级联动菜单需要进行以下几个步骤:
-
创建模型:定义三个相关联的模型,例如国家、省份和城市。
-
注册模型到admin后台:在admin.py文件中注册这些模型。
-
实现联动逻辑:利用Django 视图和JavaScript实现三级联动。
下面是一个详细的示例:
1. 创建模型
在你的models.py文件中定义三个模型:国家(Country)、省份(Province)和城市(City)。
from django.db import models
class Country(models.Model):
name = models.CharField(max_length=100)
def __str__(self):
return self.name
class Province(models.Model):
name = models.CharField(max_length=100)
country = models.ForeignKey(Country, on_delete=models.CASCADE)
def __str__(self):
return self.name
class City(models.Model):
name = models.CharField(max_length=100)
province = models.ForeignKey(Province, on_delete=models.CASCADE)
def __str__(self):
return self.name
2. 注册模型到admin后台
在你的admin.py文件中注册这些模型。
from django.contrib import admin
from .models import Country, Province, City
admin.site.register(Country)
admin.site.register(Province)
admin.site.register(City)
Django视图返回字典格式的JSON响应
from django.http import JsonResponse
from .models import Province, City
def province_by_country(request, country_id):
provinces = Province.objects.filter(country_id=country_id).order_by('name')
province_dict = {province.id: province.name for province in provinces}
return JsonResponse(province_dict)
def city_by_province(request, province_id):
cities = City.objects.filter(province_id=province_id).order_by('name')
city_dict = {city.id: city.name for city in cities}
return JsonResponse(city_dict)
更新URL配置 (urls.py
)
from django.urls import path
from . import views
urlpatterns = [
path('admin/app_name/province_by_country/<int:country_id>/', views.province_by_country, name='province_by_country'),
path('admin/app_name/city_by_province/<int:province_id>/', views.city_by_province, name='city_by_province'),
]
3. 实现联动逻辑
使用JavaScript来实现联动逻辑。
document.addEventListener('DOMContentLoaded', function () {
const countrySelect = document.getElementById('id_country');
const provinceSelect = document.getElementById('id_province');
const citySelect = document.getElementById('id_city');
function addEmptyOption(selectElement) {
const emptyOption = document.createElement('option');
emptyOption.value = '';
emptyOption.text = '请选择';
selectElement.add(emptyOption, 0);
}
function resetSelect(selectElement) {
selectElement.length = 0;
addEmptyOption(selectElement);
}
addEmptyOption(provinceSelect);
addEmptyOption(citySelect);
countrySelect.addEventListener('change', function () {
const countryId = this.value;
resetSelect(provinceSelect);
resetSelect(citySelect);
if (!countryId) {
return;
}
fetch(`/admin/app_name/province_by_country/${countryId}/`)
.then(response => response.json())
.then(data => {
for (const key in data) {
const option = document.createElement('option');
option.value = key;
option.text = data[key];
provinceSelect.add(option);
}
});
});
provinceSelect.addEventListener('change', function () {
const provinceId = this.value;
resetSelect(citySelect);
if (!provinceId) {
return;
}
fetch(`/admin/app_name/city_by_province/${provinceId}/`)
.then(response => response.json())
.then(data => {
for (const key in data) {
const option = document.createElement('option');
option.value = key;
option.text = data[key];
citySelect.add(option);
}
});
});
});