如何在Django Admin中根据下拉框值过滤另一下拉框选项?
实现Django Admin订单页面店铺与商品的联动下拉
首先先修正你模型代码里的笔误(避免后续运行报错):
class Shop(models.Model): # 示例字段,可根据实际需求添加 name = models.CharField(max_length=100) ... class Item(models.Model): # 原代码是model.Models,应为models.Model shop = models.ForeignKey('Shop', on_delete=models.CASCADE) name = models.CharField(max_length=100) ... class Order(models.Model): # 原代码是models.Models,应为models.Model shop = models.ForeignKey('Shop', on_delete=models.CASCADE) item = models.ForeignKey('Item', on_delete=models.CASCADE) ...
接下来分三步实现联动功能:
1. 后端编写AJAX接口,返回指定店铺的商品列表
在对应app的views.py中添加视图函数:
from django.http import JsonResponse from .models import Item def get_items_by_shop(request): shop_id = request.GET.get('shop_id') # 筛选指定店铺的商品,返回id和名称用于下拉选项 items = Item.objects.filter(shop_id=shop_id).values('id', 'name') return JsonResponse(list(items), safe=False)
在项目或app的urls.py中配置路由:
from django.urls import path from . import views urlpatterns = [ # 其他已有路由... path('get-items-by-shop/', views.get_items_by_shop, name='get_items_by_shop'), ]
2. 自定义Order的Admin类,注入前端JS
在app的admin.py中修改Order的Admin配置,引入自定义JS文件:
from django.contrib import admin from .models import Order class OrderAdmin(admin.ModelAdmin): # 配置创建订单页面显示的字段 fields = ('shop', 'item') # 引入静态JS文件 class Media: js = ('js/order_admin.js',) # 路径对应static文件夹下的js目录 admin.site.register(Order, OrderAdmin)
3. 编写前端JS实现下拉联动逻辑
在项目的static/js目录下创建order_admin.js文件,添加以下代码:
document.addEventListener('DOMContentLoaded', function() { const shopSelect = document.getElementById('id_shop'); const itemSelect = document.getElementById('id_item'); // 保存初始的商品选项,用于清空后恢复 const originalItemOptions = Array.from(itemSelect.options); // 监听店铺下拉框的选择变化 shopSelect.addEventListener('change', function() { const shopId = this.value; itemSelect.innerHTML = ''; if (!shopId) { // 未选择店铺时,恢复初始商品选项 originalItemOptions.forEach(opt => itemSelect.appendChild(opt)); return; } // 发送AJAX请求获取对应店铺的商品 fetch(`/get-items-by-shop/?shop_id=${shopId}`) .then(res => res.json()) .then(data => { // 添加默认空选项 const emptyOpt = document.createElement('option'); emptyOpt.value = ''; emptyOpt.textContent = '---------'; itemSelect.appendChild(emptyOpt); // 遍历添加商品选项 data.forEach(item => { const opt = document.createElement('option'); opt.value = item.id; opt.textContent = item.name; itemSelect.appendChild(opt); }); }) .catch(err => console.error('加载商品失败:', err)); }); });
注意事项
- 确保Django项目已正确配置静态文件路径,
static文件夹可被访问 - 如果项目有app命名空间,需要调整
fetch中的URL路径(比如/your-app-name/get-items-by-shop/) - 外键字段必须添加
on_delete参数,这是Django 2.0+的强制要求
内容的提问来源于stack exchange,提问作者Helen
相关产品推荐
相关产品推荐

