我想过滤tastypie中的结果,以获得符合同一领域的两个过滤器的结果。
所以,如果我有一个像这样的简单模型......
class Item(models.Model):
name = models.CharField(max_length=255)
description = models.TextField()
使用ModelResource ...
class ItemResource(ModelResource):
...
class Meta():
queryset = Item.objects.all()
resource_name = 'item'
filtering = {'name': ALL, 'description': ALL}
我可以在tastypie的网址中轻松构建“AND”查询:
/api/v1/item/?name__contains=hello&description__contains=foo
但是如果我想在同一个字段上构造一个AND运算符,它只需要第二个参数并忽略第一个参数。也就是说,
/api/v1/item/?name__contains=hello&name__contains=world
返回名称字段包含'world'的资源,但不返回名称字段包含'hello'和'world'的资源。
我理解如何直接在django中执行此操作:
Item.objects.filter(name__contains='hello').filter(name__contains='world')
但是如何在tastypie的URL中构建这种查询?
答案 0 :(得分:0)
我正在使用以下内容。它将为您提供name__contains=hello,world
的支持。你也可以做出否定name__contains!=foo
。
def build_filters(self, filters=None):
"""
Adds support for negation filtering
"""
if not filters:
return filters
applicable_filters = {}
self.filters = filters
# Normal filtering
filter_params = dict([(x, filters[x]) for x in filter(lambda x: not x.endswith('!'), filters)])
applicable_filters['filter'] = super(MainBaseResource, self).build_filters(filter_params)
# Exclude filtering
exclude_params = dict([(x[:-1], filters[x]) for x in filter(lambda x: x.endswith('!'), filters)])
applicable_filters['exclude'] = super(MainBaseResource, self).build_filters(exclude_params)
return applicable_filters
def apply_filters(self, request, applicable_filters):
"""
Adds support for:
1. negation filtering: value_date__year!=2013
2. multiple filtering value_date__year=2013,2012
"""
from django.db.models import Q
import operator
from types import *
objects = self.get_object_list(request)
f = applicable_filters.get('filter')
if f:
# Q Filters for multiple values (1,2,3 etc)
q_filters = []
for key, val in f.iteritems():
string = str(val)
if ',' in string:
for excl_filter in string.split(','):
q_filters.append((key, excl_filter))
q_list = [Q(x) for x in q_filters]
for x in q_filters:
try:
del f[x[0]]
except:
pass
if q_list:
objects = objects.filter(reduce(operator.or_, q_list), **f)
else:
objects = objects.filter(**f)
e = applicable_filters.get('exclude')
if e:
objects = objects.exclude(**e)
return objects