ICode9

精准搜索请尝试: 精确搜索
首页 > 编程语言> 文章详细

python – Django的.annotate()可以返回对象吗?

2019-06-10 09:45:39  阅读:323  来源: 互联网

标签:python django annotate


我有一个看起来像这样的记录集(省略了无关的数据以保护容易无聊):

 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"))
)

问题是我想要对象,而不是单个词典列表.我需要附加到这些对象的方法可用.关于如何做到这一点的任何想法?

编辑:
我应该指出我尝试使用.values()因为没有它我会得到一堆带注释的对象,但是会有8个(如上面的第一个查询中),而不是2(如第二个)结果如上).我的猜测是它没有组合行,因为在那里有一个时间戳使行不同:

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

解决方法:

当我最初提出这个问题时,看起来有些混乱,因此我被指示不使用.values(),而实际上并不是问题.问题是Django的.annotate()不允许用计算值覆盖列属性,只允许用附加数据注释对象.这实际上是有道理的,因为如果你想要一个返回的对象,你希望能够假设有问题的对象实际上代表了数据库中的一行,而不是计算值的混合覆盖列值.

但是,这对我来说不起作用,因为上面的功能意味着对于像创建的列(时间戳),你不能使用.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())

使用.defer()可能已经为我做了这个,虽然there appears to be a bug in Django 1.3 when combining that with .annotate()

标签:python,django,annotate
来源: https://codeday.me/bug/20190610/1211074.html

本站声明: 1. iCode9 技术分享网(下文简称本站)提供的所有内容,仅供技术学习、探讨和分享;
2. 关于本站的所有留言、评论、转载及引用,纯属内容发起人的个人观点,与本站观点和立场无关;
3. 关于本站的所有言论和文字,纯属内容发起人的个人观点,与本站观点和立场无关;
4. 本站文章均是网友提供,不完全保证技术分享内容的完整性、准确性、时效性、风险性和版权归属;如您发现该文章侵犯了您的权益,可联系我们第一时间进行删除;
5. 本站为非盈利性的个人网站,所有内容不会用来进行牟利,也不会利用任何形式的广告来间接获益,纯粹是为了广大技术爱好者提供技术内容和技术思想的分享性交流网站。

专注分享技术,共同学习,共同进步。侵权联系[81616952@qq.com]

Copyright (C)ICode9.com, All Rights Reserved.

ICode9版权所有