Django Admin内联创建视图如何过滤数据?仅展示当前客户产品
解决Django Admin内联下拉仅显示当前客户产品的问题
方法一:自定义内联表单实现动态过滤
假设你的模型结构大致如下(可根据实际情况调整字段名):
# models.py from django.db import models class Client(models.Model): name = models.CharField(max_length=100) # 其他业务字段 class Product(models.Model): name = models.CharField(max_length=100) client = models.ForeignKey(Client, on_delete=models.CASCADE, related_name="products") # 其他业务字段 class ContractProduct(models.Model): client = models.ForeignKey(Client, on_delete=models.CASCADE) product = models.ForeignKey(Product, on_delete=models.CASCADE) # 其他业务字段
首先定义一个自定义表单,在初始化时根据当前关联的客户过滤产品选项:
# admin.py from django import forms from .models import ContractProduct, Product class ContractProductInlineForm(forms.ModelForm): class Meta: model = ContractProduct fields = "__all__" def __init__(self, *args, **kwargs): super().__init__(*args, **kwargs) # 获取当前内联关联的客户实例 current_client = self.instance.client if current_client: self.fields["product"].queryset = Product.objects.filter(client=current_client)
接着在自定义的内联类中使用这个表单,并通过get_formset确保新增空白表单时也能拿到父客户对象:
from django.contrib import admin from .models import Client, ContractProduct class ContractProductInline(admin.TabularInline): model = ContractProduct form = ContractProductInlineForm extra = 1 def get_formset(self, request, obj=None, **kwargs): formset = super().get_formset(request, obj, **kwargs) # 给新增的空白表单设置产品过滤条件 if obj: formset.form.base_fields["product"].queryset = Product.objects.filter(client=obj) return formset @admin.register(Client) class ClientAdmin(admin.ModelAdmin): inlines = [ContractProductInline]
方法二:直接在內联类中重写字段过滤方法
如果不想单独写表单类,也可以直接在内联类里重写formfield_for_foreignkey和get_formset:
class ContractProductInline(admin.TabularInline): model = ContractProduct extra = 1 def formfield_for_foreignkey(self, db_field, request, **kwargs): field = super().formfield_for_foreignkey(db_field, request, **kwargs) # 仅对product字段应用过滤,且确保已获取到父客户对象 if db_field.name == "product" and hasattr(self, "parent_client"): field.queryset = field.queryset.filter(client=self.parent_client) return field def get_formset(self, request, obj=None, **kwargs): # 把当前客户对象保存到內联实例中,供字段过滤使用 self.parent_client = obj return super().get_formset(request, obj, **kwargs)
关键注意点
- 确认
Product模型和Client的外键关联字段名与代码一致(比如代码中用client,如果你的模型是customer要对应修改) - 如果当前客户没有关联产品,下拉列表会是空的,属于正常情况
- 两种方法都能覆盖编辑已有内联对象、新增空白内联对象的场景
内容的提问来源于stack exchange,提问作者Alejandro Echavarria
相关产品推荐
相关产品推荐

