Django tastypie:使用多个AND值筛选多对多表
我有两个表(电影和流派),它们使用交叉表(电影流派)通过多对多关系连接起来 我的models.py文件如下所示:Django tastypie:使用多个AND值筛选多对多表,django,filter,tastypie,relation,m2m,Django,Filter,Tastypie,Relation,M2m,我有两个表(电影和流派),它们使用交叉表(电影流派)通过多对多关系连接起来 我的models.py文件如下所示: class Genre( models.Model ): sName = models.CharField( max_length=176) [ .. ] class Movie( models.Model ): sTitle = models.CharField( max_length=176) genre = models.ManyToMan
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 )
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,
}
我想使用tastypie来过滤特定类型的所有电影。例如,给我看所有类型动作片、惊悚片和科幻片
我的api.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 )
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,
}
我的测试数据:
两部电影(带有流派ID)
矩阵(1和3)
叶片转轮(1和2)
首先,我对标题进行查询,如下所示,查询返回1个结果(即矩阵):
但是,我通过URL得到了三个结果,该URL应通过此查询查询相关的流派表(两次矩阵和一次Blade Runner):
http://localhost:8000/api/v1/movie/?format=json&genre__id__in=3&genre__id__in=1
我只希望能得到矩阵
我还尝试覆盖apply_过滤器,如下所示:
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
有什么办法让这一切顺利吗
谢谢你的建议…你试过
http://localhost:8000/api/v1/movie/?format=json&genre__id=3&genre__id=1
如果我理解正确,那么用
\uu in
这种方式就像说类型id\uuu in=[1,3]
我不得不同意。在中使用\u时,它将返回该列表中包含id的任何结果,如第三个应用过滤器
示例所示。@msc的解决方案的替代方案也可以是使用genre\uu id\uu-exact
或genre\uu-pk
。genre\uu-id=1与genre\uu-id\uu-exact=1相同。是的,只是提供了替代语法。从技术上讲,我应该说体裁\uuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuu谢谢你的提示,使用genre\uuuuu id,genre\uuuu id\uuuuuuu-exact为URL实现了这个技巧。伟大的但是仍然存在一个问题,如果我想用q对象创建过滤器,我在与上面示例中的两个“流派id”对象进行ANDing时仍然没有结果。。。知道为什么吗?一个有效的方法是链接过滤器,比如:oList=oList.filter(oFilter_1)、filter(oFilter_2)。。。但不知何故,我不确定为什么在apply\u filters
方法中会使查询变得如此复杂。例如,您可以使用这个oList=oList.filter(sTitle\u icontains='a',而不是类似于:loQ=[Q(**{'sTitle\u icontains':'a',Q(**{'sTitle\u icontains':'x'})]