代码之家  ›  专栏  ›  技术社区  ›  HahaMuntz

按添加字段对queryset排序

  •  0
  • HahaMuntz  · 技术社区  · 6 年前

    我正在尝试向queryset的实例添加一个额外的字段,然后按新字段对集合进行排序。 但是我得到了一个场错误( Cannot resolve keyword 'foo' into field. Choices are: ... )

    我的观点(摘要):

    def view(request):
        instances = Model.objects.all()
        for counter, instance in enumerate(instances):
            instance.foo = 'bar' + str(counter)
        instances.order_by('foo')  #this line causes trouble
        return render(request, 'template.html', {'instances': instance})
    

    我的模板:

    {% for instance in instances %}
        {{instance.foo}}
    {% endfor %}
    

    如果我不考虑 order_by 行模板按预期呈现,因此字段似乎在那里。

    为什么我会得到一个字段错误?
    如果有人能帮助我理解我做错了什么,那就太棒了。

    提前谢谢。


    我找到了一个可能的解决方案将模板更改为

    {% for instance in instances|dictsort:'foo' %}

    这很好,但据我所知,视图中的逻辑应该尽可能少,所以我认为排序应该在视图中完成。
    或者这真的是正确的方式?

    2 回复  |  直到 6 年前
        1
  •  1
  •   willeM_ Van Onsem    6 年前

    Django ORM旨在构建 数据库 询问。因此,您只能查询 数据库 “知道”。数据库不知道您自己添加的方法、属性或属性。这个 .order_by 因此没有效果,因为您“修补”了 instances 奎丽斯特。

    如果你打电话给 instances.order_by 你构造了一个 新的 奎丽斯特。这个queryset接受父对象的上下文,因此表示(稍微)修改的 查询 ,但还是一个问题。旧的queryset是否已经被评估或修补,并不重要。

    而且即使有一列 foo ,这不会有帮助,因为 instance.order_by 订购 instance QueReSET,它构造了一个新的,看起来类似于旧的,除了行是有序的。

    因此,现在必须使用Python进行排序。例如,可以构造 命令 元素 sorted(..) ,例如:

    from operator import attrgetter
    
    def view(request):
        instances = Model.objects.all()
        for counter, instance in enumerate(instances):
            instance.foo = 'bar' + str(counter)
        mydata = sorted(instances, key=attrgetter('foo'))
        return render(request, 'template.html', {'instances': mydata})

    所以现在 mydata 不再是 QuerySet ,但是 香草 list . 此外,请注意,数据库中的排序可能是 轻微地 不同于Python中的排序。在Python中,如果不是所有元素都具有相同的类型,则可能发生异常,而且不能保证order关系背后的语义完全相同。

        2
  •  0
  •   dethos    6 年前

    Python对象中的新属性不存在于数据库中,而仅存在于这些实例中。 order_by 更改存储在内存中的对象的查询集而不是当前列表。

    一种方法是在视图中使用内置的python排序函数,如: sorted 甚至 list.sort() .