如何将非数据库字段添加到数据库驱动的 Django 模型,并通过保留其数据类型的 QuerySet 设置它?
我有一个包含各种数据库模型字段的 Django 模型。 管理器的查询集之一通过一些注释调用检索各种聚合。其中一些注释是定制的,并从数据库中检索浮点值。这些注释不是模型字段的一部分。 但是,当创建查询集时,这些浮点数在模型中变成了整数,我猜是因为没有模型字段将它们绑定到浮点数或小数数据类型。
下面是一些代码来演示我的意思:
自定义聚合类。请注意,数据库将结果转换为浮点数:
class SqlCTR(aggregates.Sum):
is_ordinal = True
sql_function = 'SUM'
sql_template= "CASE WHEN sum(campaignmanager_adstats.impressions) > 0 THEN sum(campaignmanager_adstats.clicks)/sum(campaignmanager_adstats.impressions)::float ELSE 0::float END"
class CTR(Sum):
name='CTR'
def add_to_query(self, query, alias, col, source, is_summary):
aggregate = SqlCTR(col, source=source, is_summary=is_summary)
query.aggregates[alias] = aggregate
这是查询集:
camps = self.select_related(depth=3).\
annotate( impressions=Sum('ad__adstats__impressions'),\
clicks=Sum('ad__adstats__clicks'),\
ctr=CTR('ad__adstats__clicks'),\
exclude(**campaignExclude).\
filter(**campaignArgs).order_by(sortBy)
问题是,虽然查询本身运行正常并以浮点数形式返回 CTR,但将其作为浮点数排序并过滤它就好了(如果我在 Postgres 中运行生成的 sql)控制台),生成的查询集将值转换为整数,导致 0... (请记住,CTR 不是模型字段)。
我如何确保带注释的值以正确的数据类型加载到模型中?我可以设置 DecimalField 或 FloatField 的非数据库模型字段来保留类型吗?
任何想法都将受到高度赞赏!
谢谢
哈雷尔
I've got a Django model containing various database model fields.
One of the manager's querysets retrieves various aggregations via some annotate calls. Some of those annotations are custom made and retrieve float values from the database. Those annotations are not part of the model's fields.
However, when the queryset is created, those floats turn out to be integers in the model, I guess because the there's not a model field to bound them to a float or decimal data type.
Here's some code to demostrate what I mean:
The custom aggregate classes. Note the database casts the result to a float:
class SqlCTR(aggregates.Sum):
is_ordinal = True
sql_function = 'SUM'
sql_template= "CASE WHEN sum(campaignmanager_adstats.impressions) > 0 THEN sum(campaignmanager_adstats.clicks)/sum(campaignmanager_adstats.impressions)::float ELSE 0::float END"
class CTR(Sum):
name='CTR'
def add_to_query(self, query, alias, col, source, is_summary):
aggregate = SqlCTR(col, source=source, is_summary=is_summary)
query.aggregates[alias] = aggregate
And here's the queryset:
camps = self.select_related(depth=3).\
annotate( impressions=Sum('ad__adstats__impressions'),\
clicks=Sum('ad__adstats__clicks'),\
ctr=CTR('ad__adstats__clicks'),\
exclude(**campaignExclude).\
filter(**campaignArgs).order_by(sortBy)
The problem is that although the query itself runs ok and returns CTR as floats, sorts it as a float and filters it just fine (if I run the generated sql in Postgres's console), the resulting Queryset translates the value to an integer, resulting in 0s...
(Remember CTR is not a model field).
How can I either make sure that the annotated values load in their right datatype to the model? Can I set a non database model field of DecimalField or FloatField which will preserve the type?
Any idea will be highly appreciated!
Thanks
Harel
如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。
绑定邮箱获取回复消息
由于您还没有绑定你的真实邮箱,如果其他用户或者作者回复了您的评论,将不能在第一时间通知您!
发布评论
评论(3)
此代码表示在尝试下面 Omer 的建议后 django shell 的输出...似乎无法在注释中编写任何代码...
This code denomstrates output from the django shell after trying Omer's proposal below... Can't seem to write any code in the comments...
我来回答我自己的问题:
事实证明(显然),浏览 django 代码本身有很大帮助。
我的 SqlCTR 调用有:
is_ordinal = True
django 代码中的注释状态:而我需要
is_computer=True
I'll answer my own question:
Turns out (obviously), that going through the django code itself is a lot of help.
My SqlCTR call had:
is_ordinal = True
which the comments in the django code state:while I needed
is_computer=True
根据django代码中的文档:
因此,尝试将字段类型放在SqlCTR的构造函数中的source中。
应该是:
According to the documentation in the django code:
So, try putting the field type in source in the constructor of SqlCTR.
should be: