【问题标题】:Tastypie Negation FilterTastypie 否定过滤器
【发布时间】:2012-03-29 07:52:36
【问题描述】:

默认情况下是否有否定过滤器可用。这个想法是您可以在 django ORM 中执行以下操作:

model.objects.filter(field!=value)

如果可能的话,我怎么能在美味派中做到这一点。我试过了:

someapi.com/resource/pk/?field__not=value
someapi.com/resource/pk/?field__!=value
someapi.com/resource/pk/?field!=value

他们都给了我错误。

【问题讨论】:

  • 在某些情况下,您可以用类似的过滤器替换它:?field__not=null 可以替换为 ?field__isnull=false,“不大于”可以替换只需?field__lte=x(因此使用“小于等于”)。另外请记住,Django 可能会以某种方式允许您将field!=value 作为参数传递,但它会导致布尔值被进一步传递(或者NameError,如果field 不是定义的变量)。或者我错了,Django 执行运算符重载,例如。 web2py 在查询生成器的情况下会做什么?

标签: django api tastypie


【解决方案1】:

很遗憾没有。

问题在于 Tastypie 的 ModelResource 类仅使用 QuerySet 的 filter() 方法,即它不使用应该用于否定过滤器的 exclude()。没有 filter() 字段查找意味着否定。有效的查找是(在此SO post 之后):

exact
iexact
contains
icontains
in
gt
gte
lt
lte
startswith
istartswith
endswith
iendswith
range
year
month
day
week_day
isnull
search
regex
iregex

但是,实现对“__not_eq”之类的支持应该不难。您需要做的就是修改 apply_filters() 方法并使用“__not_eq”将过滤器与其余过滤器分开。然后你应该将第一组传递给 exclude(),其余的传递给 filter()。

类似:

def apply_filters(self, request, applicable_filters):
    """
    An ORM-specific implementation of ``apply_filters``.

    The default simply applies the ``applicable_filters`` as ``**kwargs``,
    but should make it possible to do more advanced things.
    """
    positive_filters = {}
    negative_filters = {}
    for lookup in applicable_filters.keys():
        if lookup.endswith( '__not_eq' ):
            negative_filters[ lookup ] = applicable_filters[ lookup ]
        else:
            positive_filters[ lookup ] = applicable_filters[ lookup ]

    return self.get_object_list(request).filter(**positive_filters).exclude(**negative_filters)

代替默认值:

def apply_filters(self, request, applicable_filters):
    """
    An ORM-specific implementation of ``apply_filters``.

    The default simply applies the ``applicable_filters`` as ``**kwargs``,
    but should make it possible to do more advanced things.
    """
    return self.get_object_list(request).filter(**applicable_filters)

应该允许以下语法:

someapi.com/resource/pk/?field__not_eq=value

我没有测试过。它可能也可以用更优雅的方式编写,但应该能让你继续前进:)

【讨论】:

  • negative_filters中过滤器的key不应该是“field__not_eq”,而是“field__exact”,所以Django ORM模块可能会处理它。此外,build_filters 必须被覆盖,因此 Tastypie 不会将“__not_eq”视为关系。
【解决方案2】:

在不更改代码的情况下执行此操作的另一种方法是使用带有 inverse matching 的 iregex

http://HOST/api/v1/resource/?format=json&thing__iregex=^((?!notThis).)*$

【讨论】:

    【解决方案3】:

    我为此打开了一个错误并在这里提供了一个简单的解决方案:https://github.com/toastdriven/django-tastypie/issues/524

    添加“!”可能会更好字段名称末尾的字符,就像您在问题中所做的那样...

    【讨论】:

      【解决方案4】:

      请注意 Gorneau 的上述答案:似乎这仅在您不使用 MySQL 后端时才有效。见:

      #1139 - Got error 'repetition-operator operand invalid' from regexp

      【讨论】:

        【解决方案5】:

        我使用 exclude() 来避免某些值。例如:

        Person.filter(name="Tim").exclude(state="Down");
        

        【讨论】:

          猜你喜欢
          • 2013-01-09
          • 2014-01-17
          • 2019-02-08
          • 2011-10-27
          • 2012-07-11
          • 1970-01-01
          • 2012-07-21
          • 1970-01-01
          • 1970-01-01
          相关资源
          最近更新 更多