0

我想过滤美味派中的结果,以获得符合同一字段上两个过滤器的结果。

所以如果我有一个像这样的简单模型......

class Item(models.Model):
    name = models.CharField(max_length=255)
    description = models.TextField()

使用模型资源...

class ItemResource(ModelResource):
    ...
    class Meta():
        queryset = Item.objects.all()
        resource_name = 'item'
        filtering = {'name': ALL, 'description': ALL}

我可以轻松地在tastepie 的url 中构造“AND”查询:

/api/v1/item/?name__contains=hello&description__contains=foo

但是如果我想在同一个字段上构造一个 AND 运算符,它只需要第二个参数而忽略第一个参数。那是,

/api/v1/item/?name__contains=hello&name__contains=world

返回名称字段包含“世界”的资源,但不返回名称字段同时包含“你好”和“世界”的资源。

我了解如何直接在 django 中执行此操作:

Item.objects.filter(name__contains='hello').filter(name__contains='world')

但是,我如何在tastepie 的URL 中构造这种查询呢?

4

1 回答 1

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
于 2013-10-04T00:28:00.510 回答