我的目标是过滤涉及植物的模型。下面是我的模型的缩写:
class Plant(models.Model):
sku = models.CharField('SKU', max_length=14)
name = models.CharField('Name', max_length=50)
genus = models.ForeignKey(Genus, on_delete=models.SET_NULL, null=True, blank=True)
class Meta:
ordering = ['genus', 'name']
def __str__(self):
return self.name
我的相关模型Genus非常简单,只有两个领域:
class Genus(models.Model):
common = models.CharField('Common Genus', max_length=100)
latin = models.CharField('Latin Genus', max_length=100)
class Meta:
ordering = ['common']
verbose_name_plural = 'genera'
def __str__(self):
return self.common
这里的意思是,Genus的条目有时与latin
的值相同。例如Cherry,Peach和Almond都是prunus,但每个都有自己的条目。
{
[
'common': 'Cherry',
'latin': 'Prunus'
],
[
'common': 'Almond',
'latin': 'Prunus'
],
[
'common': 'Peach',
'latin': 'Prunus'
]
}
我使用django-filter
过滤这些值时出现问题。我有一个通用名称过滤器和一个拉丁名称过滤器。通用名称过滤器很简单,因为通用名称将始终是唯一的,但是拉丁名称在许多条目中可能是通用的。
class LatinChoiceField(ModelChoiceField):
def label_from_instance(self, obj):
return obj.latin
class LatinFilter(django_filters.ModelChoiceFilter):
field_class = LatinChoiceField
class ProductFilter(django_filters.FilterSet):
genus__common = django_filters.ModelChoiceFilter(queryset=Genus.objects.all(), label='Genus')
latin_q = Genus.objects.all().order_by('latin')
genus__latin = LatinFilter(queryset=latin_q, label='Latin', field_name='genus')
class Meta:
model = Product
fields = ['genus__common', 'genus__latin']
这将为我提供大部分,但是问题是ModelChoiceFilter
将重复拉丁名称的每个值,给了我一个select
输入,该输入多次重复“ Prunus”,每个重复仅与Genus
模型条目的主键有关。
http://127.0.0.1:8000/plants/?genus__latin=7
产品:
Almond
同时:
http://127.0.0.1:8000/plants/?genus__latin=4
产品:
Cherry
如何将所有类似的拉丁值按名称或一组主键分组在一起?
http://127.0.0.1:8000/plants/?genus__latin='Prunus'
http://127.0.0.1:8000/plants/?genus__latin=7,4,2
应产生:
Almond, Cherry, Peach
似乎您正在寻找的实际上是AllValuesFilter
。有了它,您的代码将如下所示:
class ProductFilter(django_filters.FilterSet):
genus__common = django_filters.ModelChoiceFilter(queryset=Genus.objects.all(), label='Genus')
genus__latin = AllValuesFilter(label='Latin')
class Meta:
model = Product
fields = ['genus__common', 'genus__latin']