J'ai deux tables (Movie et Genre) qui sont connectées avec une relation many to many en utilisant un crosstable (MovieGenre).tastypie: filtre beaucoup à plusieurs tables avec plusieurs, valeurs ANDed
Mon fichier models.py ressemble à ceci:
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)
Je veux utiliser tastypie pour filtrer tous les films de certains genres. Par exemple. montre moi tous les films de genre Action, Thriller et SciFi.
Mon api.py ressemble à ceci:
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,
}
Mes données de test: Deux films (avec ids genre) Matrix (1 & 3) Blade Runner (1 & 2)
D'abord je fais une requête sur le titre, comme attendu ci-dessous la requête renvoie 1 résultat (à savoir Matrix):
http://localhost:8000/api/v1/movie/?format=json&sTitle__icontains=a&sTitle__icontains=x
Cependant, je reçois trois résultats avec l'URL qui devrait interroger la table de genre liées (deux fois la matrice et une fois Blade Runner) avec cette requête:
http://localhost:8000/api/v1/movie/?format=json&genre__id__in=3&genre__id__in=1
j'attendre de revenir que la matrice
J'ai également essayé de substituer apply_filters comme ceci:
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
Une idée pour que cela fonctionne?
Merci pour toute idée ...
Je ne sais pas pourquoi vous avez tellement compliqué les requêtes dans votre méthode 'apply_filters'. Par exemple, au lieu de quelque chose comme: 'loQ = [Q (** {'Title__icontains ':' a '}), Q (** {'Title__icontains': 'x'})]' vous pouvez faire la même chose avec this 'oList = oList.filter (sTitle__icontains = 'a', sTitle__icontains = 'x'). distinct()' – Ngenator