我正在尝试向查询集的实例添加一个额外的字段,然后按新字段对集合进行排序。
但是我收到了字段错误(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' %}
很好,但是据我了解,视图中的逻辑应该尽可能少,因此我认为排序应该在视图中进行。
还是这实际上是正确的方法?
答案 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排序功能。