Использование Django-Filter для отношения «многие ко многим» - PullRequest
0 голосов
/ 25 сентября 2019

По сути, я использовал 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()

1 Ответ

0 голосов
/ 27 сентября 2019

Я не знаю, было ли более простое решение, но я не мог заставить Django-Filter правильно фильтровать по нескольким ключевым словам, поэтому я изменил мой views.py.Немного странно, но, поскольку ключевые слова были правильно перехвачены в строке запроса, было достаточно просто получить эти значения и поместить их в список через self.request.GET, а затем условно установить набор запросов, переданный в PublicationFilter.

keyword_list = []
        try:
            keyword_list = self.request.GET['keywords'].split(", ")
        except:
            print('No Keywords')
        if len(keyword_list) > 1:
            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)
...