Django同一模型多外键冲突及StoreAnalytics筛选需求解决咨询
解决StoreAnalytics模型按店铺类型筛选的问题
问题背景
我有StoreAnatytics模型:
class StoreAnatytics(models.Model): store = models.ForeignKey(Store, on_delete=models.CASCADE, null=True) tax_sum = models.DecimalField( max_digits=10, decimal_places=2, default=0, verbose_name="tax sum" )
关联的Store模型:
class Store(models.Model): user = models.ForeignKey(User, on_delete=models.PROTECT) name = models.CharField(max_length=128, blank=True, default="", verbose_name="store name") type = models.PositiveSmallIntegerField(choices=MARKET, default=Amazon, verbose_name="store type")
需要为StoreAnatytics添加筛选功能,支持按店铺主键和店铺类型筛选。尝试给StoreAnatytics新增指向Store的ForeignKey字段type时,出现以下错误:
ERRORS: <class 'stores.admin.StoreAnalytics'>: (admin.E202) 'dashboard.StoreAnatytics' has more than one ForeignKey to 'stores.Store'. You must specify a 'fk_name' attribute. dashboard.StoreAnatytics.type: (fields.E302) Reverse accessor for 'dashboard.StoreAnatytics.type' clashes with field name 'stores.Store.type'. HINT: Rename field 'stores.Store.type', or add/change a related_name argument to the definition for field 'dashboard.StoreAnatytics.type'. dashboard.StoreAnatytics.type: (fields.E303) Reverse query name for 'dashboard.StoreAnatytics.type' clashes with field name 'stores.Store.type'.
当前的filters.py内容:
from dashboard.models import StoreAnatytics from django_filters import rest_framework as filters class StoreAnatyticsFilter(filters.FilterSet): store = filters.CharFilter(lookup_expr="exact") class Meta: model = StoreAnatytics fields = ["store"]
现在需要解决如何添加按店铺类型筛选的功能。
解决方案
不需要给StoreAnatytics新增ForeignKey字段,直接通过关联模型字段筛选即可,步骤如下:
- 修改
filters.py,添加针对store__type的筛选字段:
from dashboard.models import StoreAnatytics from django_filters import rest_framework as filters class StoreAnatyticsFilter(filters.FilterSet): store = filters.CharFilter(lookup_expr="exact") # 添加店铺类型筛选,用NumberFilter接收类型对应数值 type = filters.NumberFilter(field_name="store__type", lookup_expr="exact") # 若需要下拉选择样式,可改用ModelChoiceFilter: # type = filters.ModelChoiceFilter( # queryset=Store.objects.values_list('type', flat=True).distinct(), # field_name="store__type" # ) class Meta: model = StoreAnatytics fields = ["store", "type"]
核心原理:
- Django ORM支持通过双下划线
__跨关联模型查询字段,store__type表示关联的Store模型中的type字段 - 新增的
type筛选字段通过field_name指定目标关联字段,无需修改原有模型结构,彻底避免多ForeignKey冲突问题
- Django ORM支持通过双下划线
若在Django Admin中使用筛选,直接在Admin类配置
list_filter即可:
from django.contrib import admin from .models import StoreAnatytics @admin.register(StoreAnatytics) class StoreAnatyticsAdmin(admin.ModelAdmin): list_filter = ('store', 'store__type')
内容的提问来源于stack exchange,提问作者Iren E
相关产品推荐
相关产品推荐

