按 @property 对 Django queryset 进行排序

30

我正在尝试按照我在模型中定义的属性对查询集进行排序,但不确定最佳方法是什么。这是属性:

@property
def name(self):
    if self.custom_name:
        return self.custom_name
    else:
        return self.module_object.name

基本上,我想要做一个:

things = Thing.objects.all().order_by('-name')

但当渲染时遇到 Caught FieldError 错误:无法将关键字 'name' 解析为字段。

有任何想法吗?

编辑:我明白不能以这种方式进行排序,因为 @property 不是数据库字段。我的问题是,鉴于 @property 不是数据库字段,如何进行排序。

4个回答

44

你无法这样做,因为该属性不在MySQL中,而是在你的Python代码中。如果你真的想这样做,你可以在客户端上实现(尽管速度会非常慢):

sorted(Thing.objects.all(), key=lambda t: t.name)

这个几乎可以工作,但是返回的排序有些奇怪。基本上,具有self.custom_name的元素被排序,然后具有self.module_object.name的元素被排序。 - Brenden
1
没关系。我只需要在名称后面添加 .lower() 来进行不区分大小写的排序。 - Brenden

4

order_by 是在 SQL 层面进行的操作,因此它无法利用属性,只能使用字段数据。

可以查看 queryset API,你可能可以使用例如 extra 来注解查询并对其进行排序。


谢谢。我已经看了Extra,但不确定如何将@property合并到其中。 - Brenden
@brenden,你不是直接加入属性。在我的例子中,我需要status=DRAFT (其中DRAFT='draft')首先出现。所以,我使用了extra在select语句中插入了一个draft列,如果status=DRAFT(排除status=DONE)就为true,并按照它进行排序:MyModel.objects.exclude(status=DONE).extra(select={'draft': 'status = %s'}, select_params=[DRAFT]).order_by('-draft')。 - MagicLAMP

4

看一下django-denorm。它可以让你在数据库中维护计算值(然后你可以使用这些值来高效地排序),只需添加一个方法装饰器。


3

您只能按数据库字段排序。您可以获取所有记录并将其转换为列表,然后进行排序,但这可能效率低下且速度较慢。

或者,您可以通过 post-save 钩子添加一个名为 name 的数据库字段,并填充它;然后您可以使用 order_by 进行排序。


网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接