基本上,我一直在使用Django-Filter来过滤有关各个领域的大量出版物。一个字段是关键字,它通过PublicationKeywords表具有多对多关系。该模型如下所示(保留某些字段和信息):
class Publication(models.Model):
keywords = models.ManyToManyField(Keyword, through='PublicationKeywords')
class Keyword(models.Model):
value = models.CharField(max_length=100)
class PublicationKeywords(models.Model):
keyword = models.ForeignKey(Keyword, db_column='keyword_id',
on_delete=models.SET_NULL,
null=True)
publication = models.ForeignKey(Publication, db_column='publication_id',
on_delete=models.SET_NULL,
null=True)
在这种情况下是否可以使用ModelChoiceFilter或ModelMultipleChoiceFilter来进行类似于
的操作PublicationKeywords.objects.filter(keyword__value_in=keyword_list).distinct('publication')
基本过滤器设置如下
class PublicationFilter(django_filters.FilterSet):
title = django_filters.CharFilter(lookup_expr='icontains')
state = django_filters.ChoiceFilter(
choices=STATE_CHOICES)
sac = django_filters.ModelChoiceFilter(queryset=Sac.objects.all())
published_date_after = DateFilter(
field_name='published_date', lookup_expr=('gte'))
published_date_before = DateFilter(
field_name='published_date', lookup_expr=('lte'))
data_begin_year = django_filters.NumberFilter(
lookup_expr='gte')
data_end_year = django_filters.NumberFilter(
lookup_expr='lte')
keywords = django_filters.ModelMultipleChoiceFilter(queryset=?)
# TODO figure out how to get this keywords filter to work like
# PublicationKeywords.objects.filter(keyword__value_in=keyword_list).distinct('publication')
class Meta:
model = Publication
strict = False
fields = ['title', 'state', 'sac', 'published_date',
'data_begin_year', 'data_end_year', 'keywords']
def __init__(self, *args, **kwargs):
super(PublicationFilter, self).__init__(*args, **kwargs)
if self.data == {}:
self.queryset = self.queryset.none()
我不知道是否有一个更简单的解决方案,但是我无法让Django-Filter正确地按多个关键字进行过滤,因此我更改了views.py。有点骇人听闻,但是由于关键字已正确地捕获在查询字符串中,因此很容易捕获这些值并将它们通过self.request.GET放入列表中,然后有条件地更改在PublicationFilter中传递的queryset arg。
keyword_list = []
try:
keyword_list = self.request.GET['keywords'].split(", ")
except:
print('No Keywords')
if len(keyword_list) > 0:
filter_list = PublicationFilter(
self.request.GET, queryset=Publication.objects.filter(keywords__value__in=keyword_list).distinct())
else:
filter_list = PublicationFilter(
self.request.GET, queryset=Publication.objects.all())
paginator = Paginator(filter_list.qs, 10)