【问题标题】:Ordering Django queryset by a @property [duplicate]通过@property 订购Django 查询集[重复]
【发布时间】:2012-01-18 16:38:47
【问题描述】:

我正在尝试通过我在模型中定义的属性来订购查询集,但不确定执行此操作的最佳方法。这是属性:

@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:无法将关键字“名称”解析为字段。

有什么想法吗?

编辑:我知道我不能这样排序,因为@property 不是数据库字段。我的问题是如何排序,因为@property 不是数据库字段。

【问题讨论】:

    标签: python django


    【解决方案1】:

    order_by发生在sql级别,所以不能使用属性,只能使用字段数据。

    看看queryset api,你也许可以使用例如extra 注释您的查询并对其进行排序

    【讨论】:

    • 谢谢 .. 我看过 Extra 但不确定如何将 @property 合并到其中
    • @brenden,您没有合并该属性。在我的示例中,我需要先设置 status=DRAFT(其中 DRAFT='draft')。因此,我使用 extra 在 select 语句中插入了一个草稿列,如果 status=DRAFT(不包括 status=DONE)则为 true,并对其进行排序,如下所示:MyModel.objects.exclude(status=DONE).extra(select={ 'draft': 'status = %s'}, select_params=[DRAFT]).order_by('-draft')
    【解决方案2】:

    您只能按数据库字段排序。您可以提取所有记录,将它们变成一个列表,然后对它们进行排序,尽管这可能效率低下且速度慢。

    或者您可以添加一个名为name 的数据库字段并通过保存后挂钩填充它;然后你可以使用order_by对其进行排序。

    【讨论】:

      【解决方案3】:

      您不能这样做,因为该属性不在 MySQL 中,而是在您的 python 代码中。如果你真的想这样做,你可以在客户端(虽然它会很慢):

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

      【讨论】:

      • 这几乎可以工作,但它返回奇怪的排序。基本上,带有 self.custom_name 的排序,然后排序带有 self.module_object.name 的。
      • 没关系。我只需要在不区分大小写的排序名称后添加一个 .lower()
      【解决方案4】:

      看看django-denorm。它可以让您以单个方法装饰器的成本维护数据库中的计算值(然后您可以使用它来进行有效排序)。

      【讨论】:

        猜你喜欢
        • 2013-03-25
        • 1970-01-01
        • 2014-02-11
        • 2013-01-12
        • 2023-03-10
        • 2016-03-02
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        相关资源
        最近更新 更多