我试图像这样为PostgreSQL width_bucket
编写一个Django包装器:
from django.db.models import Func
from django.db import models
class Log2Bucket(Func):
template = "width_bucket(%(expressions)s::double precision[])"
def __init__(self, expression, a, b, **extra):
buckets = []
while a <= b:
buckets.append(str(a))
a *= 2
buckets = Value(buckets, output_field=ArrayField(models.FloatField()))
super().__init__(expression, buckets,
output_field=models.PositiveSmallIntegerField(), **extra)
这适用于像
这样的查询Foo.objects.annotate(b=Log2Bucket('bar', 125, 100000)).values('b')
但是
from django.db.models import Count
(Foo.objects.annotate(b=Log2Bucket('bar', 125, 100000))
.values('b').annotate(count=Count('pk')))
我从Django里面得到一个TypeError: unhashable type: 'list'
。
如果我使用
buckets = Value(tuple(buckets), output_field= ...
我仍然从同一个地方获得TypeError: unhashable type: 'list'
。
我该如何解决这个问题?是否有一种方法可以减少这种功能?
我尝试使用我升级到PostgreSQL 10并且这个走了。function = 'width_bucket'
代替template = ...
,但后来我收到了PostgreSQL错误function width_bucket(double precision, numeric[]) does not exist
。
答案 0 :(得分:0)
我成功地解决了这个问题:
class Log2Bucket(Func):
function = 'width_bucket'
def __init__(self, expression, a, b, **extra):
buckets = []
while a <= b:
buckets.append(str(a))
a *= 2
buckets = Value("{%s}" % ','.join(map(str, buckets)))
super().__init__(expression, buckets,
output_field=models.PositiveSmallIntegerField(), **extra)
哪个有效,但不漂亮。