简体   繁体   English

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

[英]Sort queryset by added field

I'm trying to add an extra field to the instances of my queryset and then sort the set by the new field. 我正在尝试向查询集的实例添加一个额外的字段,然后按新字段对集合进行排序。 But I get a field error( Cannot resolve keyword 'foo' into field. Choices are: ... ) 但是我收到一个字段错误( Cannot resolve keyword 'foo' into field. Choices are: ...

My view(abstract): 我的观点(摘要):

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})

My template: 我的模板:

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

If I leave out the order_by line the templates renders as expected, so the field seems to be there. 如果我省略了order_by行,则模板将按预期方式渲染,因此该字段似乎在那里。

So why do I get a field error? 那么为什么会出现字段错误?
It would be awesome, if somebody could help me to understand what I'm doing wrong. 如果有人可以帮助我了解我在做错什么,那将很棒。

Thanks in advance. 提前致谢。


I found a possible solution to change the template to 我找到了将模板更改为的可能解决方案

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

and that works fine, but from what I understand there should be as little logic as possible in the view, so I figure sorting should be done in the view. 而且效果很好,但是据我了解,视图中的逻辑应该尽可能少,因此我认为应该在视图中进行排序。
Or is this actually the right way? 还是这实际上是正确的方法?

The Django ORM aims to construct database queries. Django ORM旨在构建数据库查询。 As a result, you can only query on what a database "knows". 结果,您只能查询数据库 “知道”什么。 Methods, properties, or attributes you added yourself are unknown to the database. 您自己添加的方法,属性或属性对于数据库是未知的。 The .order_by thus has no effect, since you "patched" the objects in the instances queryset. 因此, .order_by无效,因为您已“修补” instances集中的对象。

If you however call an instances.order_by you construct a new queryset. 但是,如果您调用instances.order_by则会构造一个新的查询集 This queryset takes the context of the parent, and thus represents a (slightly) modified query , but again, a query. 此查询集采用父级的上下文,因此表示(略微)修改的查询 ,但还是一个查询。 Whether the old queryset is already evaluated or patched, is of no importance. 旧的查询集是否已被评估或打补丁并不重要。

Furthermore even if there was a column foo , it would not help, since the instance.order_by does not order the instance queryset, it constructs a new one, one that looks approximately like the old one, except that the rows are ordered. 而且即使有一列foo ,也不会帮助,因为instance.order_by 责令instance查询集,构建一个新的,一个看起来大约类似于旧的,只是行是有序的。

You thus will have to sort in Python now. 因此,您现在必须使用Python进行排序。 You can for example construct a list of ordered elements with sorted(..) , like: 例如,您可以使用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})

So now mydata is no longer a QuerySet , but a vanilla list . 所以现在mydata不再是一个QuerySet ,但香草 list Furthermore note that ordering in a database might be slightly different than ordering in Python. 此外请注意,数据库中的排序可能与Python中的排序略有不同。 In Python exceptions can occur if not all elements have the same type, and furthermore it is not guaranteed that the semantics behind the order relation is exactly the same. 在Python中,如果并非所有元素都具有相同的类型,则可能会发生异常,此外,不能保证顺序关系后面的语义完全相同。

The new attribute in the Python Objects does not exist in the database and only in those instances. Python对象中的new属性在数据库中不存在,仅在那些实例中不存在。 order_by changes the queryset and not your current list of objects stored in memory. order_by更改查询集,而不更改您当前存储在内存中的对象列表。

One approach would be to use the builtin python sorting functions in the view like: sorted or even list.sort() . 一种方法是在视图中使用内置的python排序功能,例如: sorted甚至list.sort()

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM