简体   繁体   English

结合Django F,Value和dict来注释查询集

[英]Combining Django F, Value and a dict to annotate a queryset

I have a scenario where I want to annotate a queryset with externally prepared data in a dict. 我有一个场景,我想在dict中使用外部准备的数据来注释查询集。 I want to do something like the following: 我想做类似以下的事情:

value_dict = {"model1": 123.4, "model2": 567.8}
qs = ModelClass.objects.annotate(
    value=Value(value_dict.get(F('model__code'), 0))
)

The results currently show all as 0 as the F() doesn't seem to be the best way to look up the dict seeing as it doesn't return a string and it is resolved further down the track. 结果当前显示为0,因为F()似乎不是查找字典的最佳方式,因为它不返回字符串并且它在轨道上进一步解析。

Your help and suggestions would be much appreciated 非常感谢您的帮助和建议

I'm currently on Python 3.6 and Django 1.11 我目前使用的是Python 3.6和Django 1.11

The closest I've come so far is to loop through the dict and union a whole bunch of filtered query sets based on the dict keys. 到目前为止,我最接近的是循环遍历dict并根据dict键联合一大堆过滤的查询集。 Like so: 像这样:

value_dict = {"model1": 123.4, "model2": 567.8}
array_of_qs = []
for k, v in value_dict.items():
    array_of_qs.append(
        ModelClass.objects.filter(model__code=k).annotate(value=Value(v))
    )
qs = array_of_qs[0].union(*array_of_qs[1:])

The qs will then have the result that I want, which is the values of the dict based on the keys of the dict annotated to each instance. 然后qs将得到我想要的结果,这是基于每个实例注释的dict键的dict值。

The beauty of this is that there is only one call to the db which is when I decide to use qs, other than that this whole process doesn't touch the DB from what I understand. 这样做的好处是只有一次调用db,这是我决定使用qs时,除此之外,整个过程不会触及我理解的数据库。

Not sure there is a better way yet but will wait to see if there are other responses before accepting this one. 不确定还有更好的方法,但在接受这个之前会等待看看是否还有其他回复。

NEW IMPROVED WORKING METHOD BELOW 以下新改进的工作方法

Unfortunately the above doesn't work with values_list or values as of this current version 1.11 of Django due to this issue: https://code.djangoproject.com/ticket/28900 遗憾的是,由于此问题,上述版本无法使用当前版本1.11的Django中的values_list或值: https ://code.djangoproject.com/ticket/28900

I devised a cleaner way below: 我在下面设计了一个更清洁的方式:

value_dict = {"model1": 123.4, "model2": 567.8}
whens = [
    When(model__code=k, then=v) for k, v in value_dict.items()
]
qs = ModelClass.objects.all().annotate(
    value=Case(
        *whens,
        default=0,
        output_field=DecimalField()
    )
)

Hope it helps someone 希望它可以帮助某人

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM