You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

Django Admin中基于ProductType动态过滤ProductCategory外键问题

Django Admin实现ProductType联动过滤ProductCategory的解决方案

你当前的代码仅能在编辑已有Product实例时,根据已保存的productType过滤productCategory,但新增Product时因无实例会显示全部分类;且修改productType后无法实时更新下拉选项——因为逻辑只在表单初始化时执行一次,缺少前端动态交互支持。以下是完整解决步骤:

步骤1:修改后端逻辑(admin.py)

更新表单初始化逻辑,并新增AJAX接口用于动态获取分类:

from django.http import JsonResponse
from django.contrib import admin
from django import forms
from .models import Product, ProductType, ProductCategory

class ProductForm(forms.ModelForm):
    class Meta:
        model = Product
        fields = '__all__'

    def __init__(self, *args, **kwargs):
        super().__init__(*args, **kwargs)
        # 编辑场景:根据已有实例的productType过滤分类
        if self.instance and self.instance.productType_id:
            self.fields['productCategory'].queryset = ProductCategory.objects.filter(
                productType=self.instance.productType
            )
        # 新增场景:初始为空下拉
        else:
            self.fields['productCategory'].queryset = ProductCategory.objects.none()

@admin.register(Product)
class ProductAdmin(admin.ModelAdmin):
    form = ProductForm

    def get_urls(self):
        from django.urls import path
        # 新增AJAX请求路由
        custom_urls = [
            path(
                'get-categories/',
                self.admin_site.admin_view(self.get_categories),
                name='get-product-categories'
            )
        ]
        return custom_urls + super().get_urls()

    def get_categories(self, request):
        # 接收前端传入的productType ID,返回对应分类列表
        product_type_id = request.GET.get('product_type_id')
        categories = ProductCategory.objects.filter(
            productType_id=product_type_id
        ).values('id', 'name') if product_type_id else []
        return JsonResponse(list(categories), safe=False)

步骤2:添加前端动态交互

在你的APP目录下创建自定义Admin模板,路径为templates/admin/[你的APP名]/product/change_form.html(例如APP名为goods,则路径为templates/admin/goods/product/change_form.html),内容如下:

{% extends "admin/change_form.html" %}

{% block extrahead %}
{{ block.super }}
<script>
document.addEventListener('DOMContentLoaded', function() {
    const typeSelect = document.getElementById('id_productType');
    const categorySelect = document.getElementById('id_productCategory');

    // 定义更新分类下拉的函数
    function refreshCategories() {
        const typeId = typeSelect.value;
        categorySelect.innerHTML = '<option value="">---------</option>';
        if (!typeId) return;

        // 发送AJAX请求获取分类
        fetch(`{% url 'admin:get-product-categories' %}?product_type_id=${typeId}`)
            .then(res => res.json())
            .then(data => {
                data.forEach(item => {
                    const option = document.createElement('option');
                    option.value = item.id;
                    option.textContent = item.name;
                    categorySelect.appendChild(option);
                });
            });
    }

    // 页面加载时初始化(编辑场景)
    refreshCategories();
    // 监听ProductType下拉框变化事件
    typeSelect.addEventListener('change', refreshCategories);
});
</script>
{% endblock %}

效果说明

  • 新增Product时,productCategory初始为空,选择productType后自动加载对应分类;
  • 编辑Product时,页面加载会自动匹配已选productType的分类,修改productType后实时更新下拉选项。

内容的提问来源于stack exchange,提问作者Amin

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.08.18 10:25:32