按添加的字段对查询集进行排序
Sort queryset by added field
我正在尝试向我的查询集实例添加一个额外字段,然后按新字段对集合进行排序。
但是我得到一个字段错误(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' %}
这很好用,但据我所知,视图中的逻辑应该尽可能少,所以我认为排序应该在视图中完成。
或者这实际上是正确的方法吗?
Django ORM 旨在构造数据库 查询。因此,您只能查询 数据库 "knows"。您自己添加的方法、特性或属性对于数据库是未知的。 .order_by
因此没有效果,因为你 "patched" instances
查询集中的对象。
但是,如果您调用 instances.order_by
,您将构建一个 new 查询集。此查询集采用父级的上下文,因此表示(略微)修改的 查询 ,但同样是一个查询。旧查询集是否已经过评估或修补并不重要。
此外,即使有列 foo
,也无济于事,因为 instance.order_by
不 对 instance
查询集进行排序, 它构造了一个新的,除了行是有序的之外,它看起来与旧的大致相同。
因此您现在必须在 Python 中进行排序。例如,您可以使用 sorted(..)
构造一个 有序 元素的列表,例如:
from operator import <b>attrgetter</b>
def view(request):
instances = Model.objects.all()
for counter, instance in enumerate(instances):
instance.foo = 'bar' + str(counter)
<b>mydata = sorted(instances, key=attrgetter('foo'))</b>
return render(request, 'template.html', {'instances': <b>mydata</b>})
所以现在 mydata
不再是 QuerySet
,而是 vanilla list
。此外请注意,数据库中的排序可能 与 Python 中的排序略有 不同。在 Python 中,如果并非所有元素都具有相同的类型,则可能会发生异常,而且不能保证顺序关系背后的语义完全相同。
Python 对象中的新属性不存在于数据库中,仅存在于那些实例中。 order_by
更改查询集,而不是您当前存储在内存中的对象列表。
一种方法是在视图中使用内置 python 排序函数,例如:sorted
甚至 list.sort()
.
我正在尝试向我的查询集实例添加一个额外字段,然后按新字段对集合进行排序。
但是我得到一个字段错误(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' %}
这很好用,但据我所知,视图中的逻辑应该尽可能少,所以我认为排序应该在视图中完成。
或者这实际上是正确的方法吗?
Django ORM 旨在构造数据库 查询。因此,您只能查询 数据库 "knows"。您自己添加的方法、特性或属性对于数据库是未知的。 .order_by
因此没有效果,因为你 "patched" instances
查询集中的对象。
但是,如果您调用 instances.order_by
,您将构建一个 new 查询集。此查询集采用父级的上下文,因此表示(略微)修改的 查询 ,但同样是一个查询。旧查询集是否已经过评估或修补并不重要。
此外,即使有列 foo
,也无济于事,因为 instance.order_by
不 对 instance
查询集进行排序, 它构造了一个新的,除了行是有序的之外,它看起来与旧的大致相同。
因此您现在必须在 Python 中进行排序。例如,您可以使用 sorted(..)
构造一个 有序 元素的列表,例如:
from operator import <b>attrgetter</b>
def view(request):
instances = Model.objects.all()
for counter, instance in enumerate(instances):
instance.foo = 'bar' + str(counter)
<b>mydata = sorted(instances, key=attrgetter('foo'))</b>
return render(request, 'template.html', {'instances': <b>mydata</b>})
所以现在 mydata
不再是 QuerySet
,而是 vanilla list
。此外请注意,数据库中的排序可能 与 Python 中的排序略有 不同。在 Python 中,如果并非所有元素都具有相同的类型,则可能会发生异常,而且不能保证顺序关系背后的语义完全相同。
Python 对象中的新属性不存在于数据库中,仅存在于那些实例中。 order_by
更改查询集,而不是您当前存储在内存中的对象列表。
一种方法是在视图中使用内置 python 排序函数,例如:sorted
甚至 list.sort()
.