Я поднимаю старую Django 1.11 кодовую базу до последних версий Django и Django Rest Framework, но я столкнулся с жесткой стеной вокруг того, как работает фильтр ?search=...
при использовании нескольких терминов в последние версии Django Rest Framework.
Вплоть до версии 3.6.3 DRF можно было выполнять запрос конечной точки ?search=term1,term2
и иметь возвращаемые объекты DRF с отношениями "многие ко многим", в которых оба условия поиска соответствует одному и тому же имени поля, например, если модель имеет поле «многие ко многим», называемое tags
, относящееся к некоторой модели Tag
, то объект с тегами cake
и baker
может быть найден DRF, запросив ?search=cake,baker
.
В кодовой базе, которую я поднимаю, (сокращенный) код для этого выглядит следующим образом:
class TagQuerySet(models.query.QuerySet):
def public(self):
return self
class Tag(models.Model):
name = models.CharField(unique=True, max_length=150)
objects = TagQuerySet.as_manager()
def _get_entry_count(self):
return self.entries.count()
entry_count = property(_get_entry_count)
def __str__(self):
return str(self.name)
class Meta:
ordering = ['name',]
class Entry(models.Model):
title = models.CharField(max_length=140)
description = models.CharField(max_length=600, blank=True)
tags = models.ManyToManyField(Tag, related_name='entries', blank=True)
def __str__(self):
return str(self.title)
class Meta:
verbose_name_plural = "entries"
ordering = ['-id']
class EntryCustomFilter(filters.FilterSet):
tag = django_filters.CharFilter(name='tags__name', lookup_expr='iexact', )
class Meta:
model = Entry
fields = [ 'tags', ]
class EntriesListView(ListCreateAPIView):
"""
- `?search=` - Searches title, description, and tags
- `&format=json` - return results in JSON rather than HTML format
"""
filter_backends = (filters.DjangoFilterBackend, filters.SearchFilter, )
filter_class = EntryCustomFilter
search_fields = ('title', 'description', 'tags__name', )
parser_classes = ( JSONParser, )
Однако такое поведение для search
произошло непреднамеренно изменено в 3.6.4 , так что вместо этого DRF теперь соответствует, только если одиночное отношение , найденное через поле "многие ко многим", соответствует всем терминам. Таким образом, запись с полем tags
, имеющая отношение к Tag(name="cake")
и Tag(name="baker")
, больше не совпадает, так как нет единственного тега, который соответствует обоим терминам, но имеется запись с Tag(name="baker of cake")
и Tag(name="teller of tales")
соответствует, так как существует одно отношение, которое соответствует обоим терминам.
Нет (по крайней мере, на момент написания) никакой документации, которую я могу найти, которая объясняет, как добиться этого более старого поведения для Фильтр generi c search
, и я не могу найти здесь ранее задаваемые вопросы о Stackoverflow о том, как заставить DRF работать снова (или даже «вообще»). Есть некоторые вопросы по поводу указанных c фильтров с именами полей, но не для search=
.
Итак: какие изменения я могу внести, чтобы ?search=...
продолжал работать как прежде, при использовании версии DRF 3.6.4+? Т.е. как можно заставить фильтр ?search=term1,term2
находить модели, в которых поля «многие ко многим» имеют отдельные отношения, которые соответствуют одному или нескольким из указанных терминов?