【问题标题】:Sort ordering in Django: possible to ignore "The" prefix when sorting?Django中的排序排序:排序时可以忽略“The”前缀吗?
【发布时间】:2011-08-28 19:13:51
【问题描述】:

这似乎是 Django 简化的那种事情,想知道是否有人对此有任何经验。

我有一张乐队表,其中一些乐队被称为“极客”(例如)。我希望它们按字母顺序出现在“G”下。

我知道我可以做一些花哨的 SQL 来动态重写它们并以这种方式排序,但是 Django 是否提供任何内置功能,以便我可以保留我的 Band.objects.all() 语法并仍然过滤自定义排序?

我知道我可以更改我的数据以包含 has_prefix 字段或其他内容,并将乐队名称存储为“Geeks, The”或其他内容,但如果可能的话,我宁愿不接触数据本身。

有什么建议吗?

【问题讨论】:

    标签: django sorting


    【解决方案1】:

    order_by() 无法做到这一点

    你可以

    1. Do some fancy SQL。如果您想让它简洁明了,您应该编写一个自定义模型管理器。
    2. 在 Python 级别而非 SQL 级别进行排序
    3. 分别存储“排序标题”和“显示标题”。

    【讨论】:

    • 我刚刚想到一件事 - 我可以在模型对象上放置一个函数,返回“Band, The”样式名称,然后对其进行排序吗?
    • order_by 在数据库级别执行,您的数据库对 python 函数一无所知。但当然,您可以在 python 级别对列表进行排序(我的回答中的#2)。
    • 对于上面的选项 3,在“排序标题”字段中存储一个正确排序的序列号可能会更好,而不是重复整个标题并改变词序。使用的空间更少。
    • @Ubuntourist 不过,这确实会花费您插入的费用。
    • @MikePelley 虽然远非完美的解决方案,但我不会担心插入时会导致数字排序字段处于不正确状态,然后会定期进行“批量”处理。跨度>
    【解决方案2】:

    这是我在最近的一个 Django 项目中的做法:

    from django.db import models
    
    SomeClass(models.Model):
        title = models.CharField()
    
        @property
        def alphabetical_title(self):
            """
            Returns an alphabetical-friendly string of a title attribute.
            """
            title = self.title
    
            # A list of flags to check each `title` against.
            starts_with_flags = [
                'the ',
                'an ',
                'a '
            ]
    
            # Check each flag to see if the title starts with one of it's contents.
            for flag in starts_with_flags:
                if title.lower().startswith(flag):
                    # If the title does indeed start with a flag, return the title with
                    # the flag appended to the end preceded by a comma.
                    return "%s, %s" % (title[len(flag):], title[:len(flag)-1])
                else:
                    pass
            # If the property did not return as a result of the previous for loop then just
            # return the title.
            return self.title
    

    由于这是一个属性,而不是数据库中的实际列,我需要先检索一个 QuerySet,然后在视图中对它进行排序。我是这样做的:

    from operator import attrgetter
    from someapp.models import SomeClass
    
    some_objects = SomeClass.objects.all()
    sorted_objects = sorted(some_objects, key=attrgetter('alphabetical_title'), reverse=False)
    

    我相信您早就找到了解决方案,但我认为无论如何发布它可能会有所帮助,因为将来其他人可能会遇到同样的问题。

    【讨论】:

      【解决方案3】:

      使用模型和上面的一些提示(通过 respondcreate),以及对 this answer 的改编,我想出了以下单行方法:

      mysortedlist = sorted([x for x in SomeClass.all()],
                     key=lambda y: re.sub("^(the|a|an) ","",y.title.lower()) )
      

      这会从 QuerySet 生成一个列表,并根据 lambda 函数对其进行排序,该函数替换标题小写版本开头的 the、a 和 an。

      【讨论】:

        猜你喜欢
        • 2016-01-25
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        相关资源
        最近更新 更多