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

如何在Django Admin中隐藏已关联当前文章的产品选项?

在Django Admin中实现文章关联产品时隐藏已选产品

我们需要在Django Admin的文章详情页中,通过内联添加ArticleProduct关联记录时,让已选过的产品不再出现在产品选择的搜索/下拉列表中,避免重复选择(虽然已经有联合唯一约束,但前端隐藏能直接提升操作体验)


1. 先修正现有Admin代码的小错误

原ProductAdminModel的search_fields字段写错了,应该对应Product模型的name字段,否则autocomplete搜索功能无法正常工作:

class ProductAdminModel(admin.ModelAdmin):
    search_fields = ['name', ]  # 替换原来的'product'为'name'

2. 自定义ArticleProduct表单,过滤已选产品

创建自定义表单,重写product字段的查询集,根据当前关联的文章排除已选产品:

from django import forms
from .models import ArticleProduct, Product

class ArticleProductForm(forms.ModelForm):
    class Meta:
        model = ArticleProduct
        fields = '__all__'

    def __init__(self, *args, **kwargs):
        # 获取父对象(当前编辑的Article实例)
        self.parent_obj = kwargs.pop('parent_obj', None)
        super().__init__(*args, **kwargs)
        
        # 优先用父对象,其次用实例关联的文章
        article = self.parent_obj or self.instance.article
        if article and article.pk:
            # 拿到已关联该文章的所有产品ID,排除这些产品
            used_product_ids = article.articleproduct_set.values_list('product_id', flat=True)
            self.fields['product'].queryset = Product.objects.exclude(id__in=used_product_ids)
        else:
            # 新增文章未保存或新增内联表单时,显示所有产品
            self.fields['product'].queryset = Product.objects.all()

3. 在内联组件中使用自定义表单

修改ArticleProductIngredientInline,指定使用上面的自定义表单,同时传递父对象给表单:

class ArticleProductIngredientInline(admin.StackedInline):
    model = ArticleProduct
    form = ArticleProductForm
    autocomplete_fields = ['product']
    extra = 0

    def get_formset(self, request, obj=None, **kwargs):
        formset = super().get_formset(request, obj, **kwargs)
        # 给每个表单传递当前编辑的Article实例
        def form_callback(form):
            def __init__(self, *args, **kwargs):
                kwargs['parent_obj'] = obj
                super(form, self).__init__(*args, **kwargs)
            form.__init__ = __init__
            return form
        formset.form = form_callback(formset.form)
        # 可选:禁止在产品选择器中直接新增产品(避免未过滤的新增)
        formset.form.base_fields['product'].widget.can_add_related = False
        return formset

效果说明

  • 编辑已有文章时,所有内联表单的产品选择器都会自动排除已关联的产品
  • 动态点击"添加另一个产品"新增的内联表单,同样会过滤已选产品
  • 后端的联合唯一约束依然保留,作为最后一道校验屏障

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.08.25 21:11:25