django中RangeField的查询(get)上限

ha5z0ras  于 12个月前  发布在  Go
关注(0)|答案(3)|浏览(111)

我想通过django queryset获取RangeField的上界。
当你有访问python对象的权限时,my_model.size_range.upper可以工作。不在查询引擎内部,不与FWhenCase..

class MyModel(models.Model):
    size_range = IntergerRangeField()

MyModel.objects.all().annotate(new_upper=F('size_range__upper') + 1)

个字符
你知道吗?

rqenqsqc

rqenqsqc1#

我找到了一个半解:

from django.db.models.functions import Upper

MyModel.objects.all().annotate(
      upper=Upper('size_range')
  ).annotate(
      new_upper=F('upper') + 1
  )

字符串
这感觉很笨拙,但至少它工作
如果有人知道更好?我相信可以直接查询原始值。

ejk8hzay

ejk8hzay2#

你想用它做什么?你可以用endswith

MyModel.objects.filter(size_range__endswith=some_value))

字符串

pgpifvop

pgpifvop3#

使用django,你可以注册custom lookup

IntegerRangeField.register_lookup(MyCustomLookup)

字符串
但是,您不能直接在RangeFieldIntegerRangeField上注册Upper,因为默认情况下,loopup使用与output_field相同的字段(例如:您想要的类型不是IntegerRangeField,而是IntegerField)。output_field必须显式。
IntegerRangeFieldUpper的自定义查找如下所示:

from django.contrib.postgres.fields import IntegerRangeField
from django.db.models.functions import Upper

class IntegerRangeUpper(Upper):
    output_field = IntegerRangeField.base_field()

IntegerRangeField.register_lookup(IntegerRangeUpper)

MyModel.objects.all().annotate(
   new_upper=F('size_range__upper') + 1
)


由于在所有类型的范围字段上具有这一点可能是有用的,并且对于具有查找的范围字段手动注册所有排列将是非常重复的,因此该过程可以被推广。
这段代码使用base_field作为output_field,基于原始代码创建新的查找类,并将它们注册到字段中。

import itertools

from django.contrib.postgres.fields import IntegerRangeField, BigIntegerRangeField, DateRangeField, DateTimeRangeField, DecimalRangeField
from django.db.models.functions import Lower, Upper

def register_range_lookup(
    field, lookup_class
):
    class CustomLookup(lookup_class):
        output_field = field.base_field()

    field.register_class_lookup(CustomLookup)    

for range_field, lookup_class in itertools.product(
    [
        IntegerRangeField,
        BigIntegerRangeField,
        DateRangeField,
        DateTimeRangeField,
        DecimalRangeField,
    ],
    [Lower, Upper],
):
    register_range_lookup(range_field, lookup_class)


此外,__lower__upper现在可以像这样用于过滤:

# Gets all instances where the lower bounds are greater than 5
MyModel.objects.all().filter(
    size_range__lower__gt=5
)

相关问题