Я пытался заставить ModelMultipleChoiceFilter работать часами и прочитал документацию по фильтрам DRF и Django.
Я хочу иметь возможность фильтровать набор веб-сайтов на основе тегов, которые были назначены им через ManyToManyField. Например, я хочу получить список веб-сайтов с тегами «Кулинария» или «Пчеловодство».
Вот соответствующий фрагмент моего текущего models.py:
class SiteTag(models.Model):
"""Site Categories"""
name = models.CharField(max_length=63)
def __str__(self):
return self.name
class Website(models.Model):
"""A website"""
domain = models.CharField(max_length=255, unique=True)
description = models.CharField(max_length=2047)
rating = models.IntegerField(default=1, choices=RATING_CHOICES)
tags = models.ManyToManyField(SiteTag)
added = models.DateTimeField(default=timezone.now())
updated = models.DateTimeField(default=timezone.now())
def __str__(self):
return self.domain
И мой текущий фрагмент views.py:
class WebsiteFilter(filters.FilterSet):
# With a simple CharFilter I can chain together a list of tags using &tag=foo&tag=bar - but only returns site for bar (sites for both foo and bar exist).
tag = django_filters.CharFilter(name='tags__name')
# THE PROBLEM:
tags = django_filters.ModelMultipleChoiceFilter(name='name', queryset=SiteTag.objects.all(), lookup_type="eq")
rating_min = django_filters.NumberFilter(name="rating", lookup_type="gte")
rating_max = django_filters.NumberFilter(name="rating", lookup_type="lte")
class Meta:
model = Website
fields = ('id', 'domain', 'rating', 'rating_min', 'rating_max', 'tag', 'tags')
class WebsiteViewSet(viewsets.ModelViewSet):
"""API endpoint for sites"""
queryset = Website.objects.all()
serializer_class = WebsiteSerializer
filter_class = WebsiteFilter
filter_backends = (filters.DjangoFilterBackend, filters.SearchFilter, filters.OrderingFilter,)
search_fields = ('domain',)
ordering_fields = ('id', 'domain', 'rating',)
Я только что тестировал строку запроса [/path/to/sites]?tags=News
и на 100% уверен, что соответствующие записи существуют, поскольку они работают (как описано) с запросом ?tag
(отсутствует s
).
Пример других вещей, которые я пробовал, выглядит примерно так:
tags = django_filters.ModelMultipleChoiceFilter(name='tags__name', queryset=Website.objects.all(), lookup_type="in")
Как я могу вернуть любой веб-сайт с SiteTag, удовлетворяющим name == A OR name == B OR name == C
?
in
lookup_type
через анализатор URL-адресов django-filter? и создать собственный фильтр. Мне все еще интересно увидеть решение моей проблемы, так как я уверен, что оно поможет кому-то еще - и в коде, который я не использую, не будет ошибок :) - person Daniel Devine   schedule 06.10.2014