按添加字段对查询集进行排序

时间:2018-08-06 14:31:13

标签: python django django-templates django-views django-orm

我正在尝试向查询集的实例添加一个额外的字段,然后按新字段对集合进行排序。 但是我收到了字段错误(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 个答案:

答案 0 :(得分:1)

Django ORM旨在构建数据库查询。结果,您只能查询数据库“知道”什么。您自己添加的方法,属性或属性对于数据库是未知的。 .order_by因此无效,因为您是在instances查询集中“修补”了对象。

如果您调用instances.order_by,则会构建一个 new 查询集。此查询集采用父级的上下文,因此表示(略微)修改的 query ,但还是一个查询。旧的查询集是否已被评估或打补丁并不重要。

此外,即使存在列foo,也无济于事,因为instance.order_by不会对instance查询集进行排序,因此它会构造一个新的一,看起来像旧的,除了行是有序的。

因此,您现在必须使用Python进行排序。例如,您可以使用sorted(..)来构造 ordered 元素的列表,例如:

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中,如果不是所有元素都具有相同的类型,则可能会发生异常,而且不能保证顺序关系后面的语义完全相同。

答案 1 :(得分:0)

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

一种方法是在sorted甚至list.sort()之类的视图中使用内置的python排序功能。