2017-10-24 3 views
0

私はPostgreSQLのwidth_bucketこのようなためにDjangoのラッパーを記述しようとしている:カスタム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'))) 

のために、私はからTypeError: unhashable type: 'list'を取得Djangoの中で。

私は

buckets = Value(tuple(buckets), output_field= ... 

を使用している場合は、私はまだ同じ場所からTypeError: unhashable type: 'list'を取得します。

これを修正するにはどうすればよいですか?この機能をよりハッキリにする方法はありますか?

template = ...の代わりにfunction = 'width_bucket'を使ってみましたが、PostgreSQLのエラーfunction width_bucket(double precision, numeric[]) does not existが表示されました。私はPostgreSQL 10にアップグレードしましたが、これはなくなりました。

+0

リストの代わりにタプルを試してください –

+0

申し訳ありませんが、それも機能しませんでした。 – Dan

+0

2つのバケット「Value(buckets、...)」と「super().__ init __(expression、buckets、 –

答えて

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) 

動作しますが、かなりされていません。

関連する問題