4

次のようなレコード セットがあります (退屈しやすい人を保護するために不要なデータは省略されています)。

 id | user_id |            created            | units
----+---------+-------------------------------+-------
  1 |       1 | 2011-04-18 15:43:02.737063+00 |    20
  2 |       1 | 2011-04-18 15:43:02.737063+00 |     4
  3 |       1 | 2011-04-18 15:46:48.592999+00 |    -1
  4 |       1 | 2011-04-19 12:02:10.687587+00 |    -1
  5 |       1 | 2011-04-19 12:09:20.039543+00 |    -1
  6 |       1 | 2011-04-19 12:11:21.948494+00 |    -1
  7 |       1 | 2011-04-19 12:15:51.544394+00 |    -1
  8 |       1 | 2011-04-19 12:16:44.623655+00 |    -1

そして、私は次のような結果を得たいと思っています:

 id | user_id |            created            | units
----+---------+-------------------------------+-------
  8 |       1 | 2011-04-19 12:16:44.623655+00 |    14
  2 |       1 | 2011-04-18 15:43:02.737063+00 |     4

だから私は自然に次のことを考えてい.annotate()ます:

u = User.objects.get(pk=1)
(MyModel.objects.filter(user=u)
        .values("id","user","created")
        .annotate(stuff=Sum("units"))
)

問題は、辞書の単一のリストではなく、objectsが必要なことです。これらのオブジェクトにアタッチされたメソッドを利用できるようにする必要があります。これを行う方法についてのアイデアはありますか?

編集: .values() を使用しようとしたことを指摘する必要がありました。これがないと、注釈付きオブジェクトの束が問題なく取得されますが、(上記の最初のクエリのように) 2 つではなく (上記の最初のクエリのように) 8 つになるためです。上記の 2 番目の結果)。私の推測では、そこにタイムスタンプがあり、行が異なるため、行を結合していないということです:

MyModel.objects.filter(user=u).annotate(Sum("units"))
# Returns 8 records, not 2 as expected
4

3 に答える 3

6

最初に質問したときに混乱があったようで、.values()実際には問題がないのに使用しないように指示されました。問題は、Django.annotate()が計算された値で列のプロパティを上書きすることを許可しておらず、追加のデータでオブジェクトに注釈を付けるだけであることです。オブジェクトを返す場合、問題のオブジェクトが実際にデータベース内の行を表し、列の値を上書きする計算値の寄せ集めではないと想定できるようにする必要があるため、これは非常に理にかなっています。

ただし、これはうまくいきませんでした。上記の機能は、created(タイムスタンプ) のような列を使用すると、必要な計算値を取得できないことを意味するため、.values()オブジェクトが得られないためです。

だから、私は次善の策を選びました: .raw():

query = """
    SELECT
        ep.product_id              AS product_id,
        ep.user_id                 AS user_id,
        MAX(ep.created)            AS created,
        SUM(eup.units)             AS units
    FROM
        ecom_unitpermission AS eup
    WHERE
        ep.user_id = 1
    GROUP BY
        ep.product_id,
        ep.user_id
"""

for perm in MyModel.objects.raw(query):
    print "%15s %3s %s" % (perm.product.name, perm.units, perm.product.somemethod())

Django 1.3 と組み合わせるとバグが発生するよう.defer()ですが、.annotate()

于 2011-04-20T09:47:48.480 に答える
3

問題は注釈ではなく、値の呼び出しです。ドキュメントは、注釈がクエリセットで機能することを明確に示しています。値のディクショナリを返し、モデルにアクセスできなくなるのは値の呼び出しです。

編集して追加: 特定のフィールドのみを戻したいが、まだモデルがある場合は、値の代わりにdeferを使用します

于 2011-04-19T14:59:17.353 に答える
0

Annotate はクエリセットを返しますが、常に辞書を返す .values() も呼び出しています。

于 2011-04-19T15:02:52.650 に答える