【问题标题】:How to Add Temporary Attribute to Django Querysets and then Merge如何将临时属性添加到 Django 查询集然后合并
【发布时间】:2016-09-23 15:50:32
【问题描述】:

所以我试图将一个临时属性添加到来自同一模型的两个单独的 QuerySet,但似乎一旦我尝试将它们合并在一起,新字段就会消失。

例子:

class IndexView(View):
    def get(self, request):
        q1 = MyModel.objects.filter(points=0)
        q2 = MyModel.objects.filter(points=100)

        for q in q1:
            q.title = 'Loser'
            print(q.title)  # Prints 'Loser'

        for q in q2:
            q.title = 'Winner'
            print(q.title)  # Prints 'Winner'

        q = q1 | q2  # Merges the two QuerySets together

        for item in q:
            print(item.title)  # ERROR: "Title" is not a field anymore apparently...

        return render(request, 'index.html', {})

我尝试了另一种使用.chain()(在另一个线程中提到)的方法,但这会将类型从QuerySet 更改为List,这是我不想要的。我将在下面发布。有没有办法在获得相同结果的同时将列表保留为 QuerySet?请注意,我希望 title 属性是临时的,以便我可以分隔模板中的项目。此外,points 过滤器不是真正的过滤器,实际上要复杂得多,因此模板标签和模型方法不是一个选项。

from itertools import chain
feed = sorted(
    chain(q1, q2),
    key=lambda instance: instance.created)

Django v1.9.6Python v3.4.3

【问题讨论】:

  • q = q1 | q2 这将创建一个全新的查询集,它将选择 q1q2 的联合。然后,当您通过q 时,您会触发一个新查询并再次从数据库中加载对象。
  • 有趣 - 那么是否有替代方法可以避免擦除我定义的临时属性?
  • 理想情况下,您可以使用annotate 将这些属性添加为查询本身的一部分,也可以使用Case 子句。您甚至不需要两个查询集和合并,只需说明数据库如何自行计算字段。
  • 或者,因为这是一个非常简单的计算,所以在模型方法中甚至直接在模板中进行:{% if q.points == 0 %}loser{else %}winner{% endif %}。同样,您只需要一个查询。
  • @spectras:嗯,我不知道该怎么做。同样,这是示例代码,我的实际代码在过滤过程中使用GenericRelationsGenericForeignKeys,所以有点太疯狂了。如果这是一个可行的选择,我想了解更多关于注释的信息。

标签: python django list filter django-queryset


【解决方案1】:

你无法做到这一点,因为当你这样做时:

q = q1 | q2

您正在执行一个新的数据库查询。没有直接的方法,你只能一起查询它们然后分别标记:

queryset = MyModel.objects.filter(Q(points=0) | Q(points=100))
for item in queryset:
    if q.points  == 0:
        q.title = 'Loser'
    elif q.points == 100:
        q.title = 'Winner'

鉴于您可能对points 有复杂的条件,您还可以为模型MyModel 创建一个方法,然后调用该函数返回一个类似于分配title 的值。

【讨论】:

  • 你能告诉我为什么你不想把它们转换成列表吗?您已经遍历了它们,因此将其保留为查询集并没有真正的好处,对吧?
  • 更多,以防我将来需要使用过滤器或模板标签,这可能需要访问 QuerySet 方法。
  • 然后尽可能多地在视图中进行过滤,而不是模板标签并将它们转换为列表。我仍然相信如果您在views.py方法中处理所有内容,模板可以获得最终数据。
  • @Hybrid> 所有 QuerySet 方法都返回新的查询集(或普通对象)。这意味着在对象上设置属性将不起作用。您已使用潜在的数据库端功能降至 annotate,或者将其设为 property
  • @ShangWang:这就是我猜最后会发生的事情,不幸的是似乎没有办法了
猜你喜欢
  • 2012-05-19
  • 2013-09-06
  • 2023-04-08
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2018-03-10
  • 1970-01-01
  • 2022-12-04
相关资源
最近更新 更多