Django 中的排序顺序:可以忽略“The”排序时的前缀?

发布于 2024-11-08 18:02:25 字数 342 浏览 0 评论 0原文

这看起来像是 Django 做的简单的事情,想知道是否有人有这方面的经验。

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

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

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

有什么建议吗?

This seems like the kind of thing Django makes simple, wondering if anyone has any experience with it.

I have a table of bands, some of whom are called 'The Geeks' (for example). I want them to appear alphabetically under 'G'.

I know I can do some fancy SQL to rewrite them on the fly and sort that way, but does Django offer anything built-in so I can keep my nice Band.objects.all() syntax and still filter on a custom sort?

I know I could change my data to include a has_prefix field or something and store the bandname as 'Geeks, The' or whatever, but I'd rather not touch the data itself if possible.

Any tips?

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(3

强者自强 2024-11-15 18:02:25

以下是我在最近的 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)

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

Here's how I did it on a recent Django project:

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

Since this is a property and not an actual column in the database I need to retrieve a QuerySet first and then sort it after the fact in a view. Here's how I did that:

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)

I'm sure you've long since found a solution but I figured it might help to post it anyways as someone else in the future might run into this same problem.

沉溺在你眼里的海 2024-11-15 18:02:25

您不能使用 order_by() 执行此操作,

您可以

  1. 执行此操作一些奇特的 SQL。如果您想保持简洁,您应该编写一个自定义模型管理器。
  2. 在Python级别进行排序,而不是SQL级别
  3. 分别存储“排序标题”和“显示标题”。

You can't do it with order_by()

You can

  1. Do some fancy SQL. If you want to keep it nice and short, you should write a custom model manager.
  2. Do sorting at Python-level, not SQL-level
  3. Store "sort title" and "display title" separately.
烟燃烟灭 2024-11-15 18:02:25

使用模型和上面的一些提示(通过respondcreate),以及这个答案,我想出了以下一行方法:

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

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

Using the model and a couple hints from the above (by respondcreate), and an adaptation of this answer, I came up with the following one line approach:

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

This generates a list from the QuerySet and sorts it according to a lambda function that replaces the, a, and an at the beginning of a lowercased version of the title.

~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文