使用Django-Filter建立多对多关系

问题描述 投票:0回答:1

基本上,我一直在使用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)

在这种情况下是否可以使用ModelChoiceFilterModelMultipleChoiceFilter来进行类似于

的操作
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()
python django django-queryset django-filter
1个回答
0
投票

我不知道是否有一个更简单的解决方案,但是我无法让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)
© www.soinside.com 2019 - 2024. All rights reserved.