【问题标题】:Django Ordering Query Set in ascending orderDjango排序查询集按升序排列
【发布时间】:2012-07-30 23:20:13
【问题描述】:

我想为这种情况按升序订购我的QuerySet

PRIORITY_CHOICES = (
(1, "P1"),
(2, "P2"),
(3, "P3"),
(4, "P4"),
(5, "P5"),
)

class Task(models.Model):
     name = models.CharField(max_length=255)
     priority = models.PositiveIntegerField(choices=PRIORITY_CHOICES)

现在,优先级可以接受 None 值。当我在查看代码中执行此操作时,问题在于订购查询集:

task_list = Task.objects.all().order_by("priority")

这将返回查询集,其中对象按优先级升序排列,无值在前。我想要升序列表,但我想在最后包含 None 值。我有一个庞大的数据库,所以我有兴趣在数据库级别完成这项工作。

【问题讨论】:

标签: django django-models django-queryset


【解决方案1】:

你可以在这样的模型中简单地这样做

class ModelName(models.Model):
    feild_1 = models.CharField( max_length=150)
    feild_2 = models.CharField( max_length=150, blank=True, null=True)

    class Meta:
        ordering = [F('order').asc(nulls_last=True)]

【讨论】:

    【解决方案2】:

    您可以使用queryset.order_by('-field')(前置“-”符号)将顺序更改为降序,但是在 Django 中没有办法告诉空值应该如何排序 - 这是数据库特定的行为。如果使用降序排序仍然首先在数据库中为您提供空值 - 使用queryset.extra(select={'order': 'custom_sql_function(priority)'}).order_by('order'),其中custom_sql_function 如果字段为空,则将字段转换为整数,并且特定于您的数据库引擎。 为了获得更快的性能,您可以在 function(field) 上创建数据库索引。

    【讨论】:

    • 谢谢,我会研究一下。
    【解决方案3】:

    这可能是你最好的选择。

    import itertools
    q = itertools.chain(
            Task.objects.filter(priority__isnull=False).order_by("priority"),
            Task.objects.filter(priority__isnull=True))
    # Then you can iterate over your custom order
    result = [(x.name, x.priority) for x in q]
    

    【讨论】:

    • 谢谢,这看起来是个不错的选择。而且我猜链函数是一个 C 级别的操作,所以我认为它不应该占用太多内存。
    • 这是一些解决方案,但我更喜欢实际返回查询集的东西,您可以在其中链接其他调用(过滤器等),以便get_query_set 为经理返回它。有什么提示吗?
    猜你喜欢
    • 1970-01-01
    • 2020-08-16
    • 1970-01-01
    • 2013-09-26
    • 2010-12-11
    • 2014-04-11
    • 2016-01-19
    • 2023-04-03
    • 1970-01-01
    相关资源
    最近更新 更多