tastypie: отфильтруйте множество таблиц с несколькими значениями ANDed
У меня есть две таблицы (Movie и Genre), которые связаны отношением "многие ко многим" с помощью перекрестной таблицы (MovieGenre).
Мой файл models.py выглядит так:
class Genre( models.Model ):
sName = models.CharField( max_length=176)
[ .. ]
class Movie( models.Model ):
sTitle = models.CharField( max_length=176)
genre = models.ManyToManyField( Genre )
[ .. ]
class MovieGenre( models.Model ):
idMovie = models.ForeignKey( Movie )
idGenre = models.ForeignKey( Genre )
Я хочу использовать вкусный пирог, чтобы отфильтровать все фильмы определенных жанров. Например, покажи мне все фильмы жанра боевик, триллер и SciFi.
Мой api.py выглядит так:
class GenreResource(ModelResource):
class Meta:
queryset = Genre.objects.all()
resource_name = 'genre'
always_return_data = True
include_resource_uri = False
excludes = ['dtCreated', 'dtModified' ]
authorization= Authorization()
authentication = SessionAuthentication()
filtering = {
"id" : ALL,
}
class MovieResource(ModelResource):
genre = fields.ManyToManyField( 'app.api.GenreResource', 'genre', full=True )
class Meta:
queryset = Movie.objects.all()
resource_name = 'movie'
authorization= Authorization()
authentication = SessionAuthentication()
always_return_data = True
include_resource_uri = False
excludes = ['dtCreated', 'dtModified' ]
filtering = {
"sTitle" : ALL,
"genre" : ALL_WITH_RELATIONS,
}
Мои тестовые данные: два фильма (с жанровыми идентификаторами) Matrix (1 & 3) Blade Runner (1 & 2)
Сначала я делаю запрос на заголовок, как и ожидалось ниже, запрос возвращает 1 результат (а именно Matrix):
http://localhost:8000/api/v1/movie/?format=json&sTitle__icontains=a&sTitle__icontains=x
Тем не менее, я получаю три результата с URL-адресом, который должен запросить таблицу связанных жанров (два раза Matrix и один раз Blade Runner) с этим запросом:
http://localhost:8000/api/v1/movie/?format=json&genre__id__in=3&genre__id__in=1
Я бы ожидал, чтобы вернуться только Матрица
Я также попытался переопределить apply_filters следующим образом:
def apply_filters(self, request, applicable_filters):
oList = super(ModelResource, self).apply_filters(request, applicable_filters)
loQ = [Q(**{'sTitle__icontains': 'a'}), Q(**{'sTitle__icontains': 'x'})]
# works as intended: one result
loQ = [Q(**{'genre__id__in': '3'}) ]
# results in one result (Matrix)
loQ = [Q(**{'genre__id__in': '1'}), Q(**{'genre__id__in': '3'}) ]
# results in no results!
loQ = [Q(**{'genre__id__in': [ 1, 3]}) ]
# results in two results Matrix and Blade Runner which is OK since obviously ORed
oFilter = reduce( operator.and_, loQ )
oList = oList.filter( oFilter ).distinct()
return oList
Есть идеи сделать эту работу?
Спасибо за любую идею...
1 ответ
Ты пытался http://localhost:8000/api/v1/movie/?format=json&genre__id=3&genre__id=1
Если я правильно понимаю, используя __in
этот путь был бы как сказать genre__id__in=[1, 3]
,