按日期时间的月/日订购 Django QuerySet?

Posted

技术标签:

【中文标题】按日期时间的月/日订购 Django QuerySet?【英文标题】:Ordering a Django QuerySet by a datetime's month/day? 【发布时间】:2011-05-13 06:46:00 【问题描述】:

我有一个人员列表,每个人都有一个生日,可以预见地存储在DateField 中。我正在尝试创建这些人的列表——按他们出生的排序(不考虑年份)——有一种“谁的生日是即将到来”显示。

我似乎无法通过此人的 datetime.month 值订购 QuerySet。有什么方法可以做到这一点而不必诉诸list()

提前致谢,如果问题需要澄清,请告诉我。

【问题讨论】:

【参考方案1】:

您可以使用QuerySet.extra() 定义月份字段并按其排序:

SomeModel.objects.extra(select='birthmonth': 'MONTH(birthdate)',
    order_by=['birthmonth']) 

【讨论】:

感谢您的快速回答!只是想澄清那些使用 PostgreSQL 将 MONTH(birthdate) 替换为 EXTRACT(MONTH FROM birthdate) 的人。 正确的方法名是额外的 尽管我很喜欢这个答案,但 QuerySet.extra() 方法似乎在砧板上,最终将被弃用。 django 文档指出,“将此方法作为最后的手段”和“这是一个旧 API,我们打算在未来某个时候弃用。”【参考方案2】:

较新版本的 django 可以查找 DateFields 和 DateTimeFields。 https://docs.djangoproject.com/en/1.11/ref/models/database-functions/#extract

MyModel.objects.order_by('birthday__month', 'birthday__day')

【讨论】:

【参考方案3】:

我使用 django 1.10.8 测试过

from django.db.models.functions import Extract
from your_project.your_app.models import Person


CHOICE_MONTH = (
    (None, '--'),
    (1, 1),
    (2, 2),
    (3, 3),
    (4, 4),
    (5, 5),
    (6, 6),
    (7, 7),
    (8, 8),
    (9, 9),
    (10, 10),
    (11, 11),
    (12, 12),
)

class PersonSearchForm(forms.Form):

    name = forms.CharField(label=u'name', required=False)
    month = forms.ChoiceField(label='month', choices=CHOICE_MONTH, required=False)

    def __init__(self, *args, **kwargs):
        self.corporation = kwargs.pop('corporation', None)
        super(PersonSearchForm, self).__init__(*args, **kwargs)

    def get_result_queryset(self):
        q = Q(corporation=self.corporation)
        if self.is_valid():
            name = self.cleaned_data['name']
            if name:
                q = q & Q(name__icontains=name)
            month = self.cleaned_data['month']
            if month:
                q = q & Q(month=int(month))

        return Person.objects.annotate(month=Extract('birthday', 'month'),
                                       day=Extract('birthday', 'day')).filter(q).order_by('month', 'day')

【讨论】:

请考虑为您的回答添加一些解释。【参考方案4】:

对于 django >= 2.1

您可以使用 DateField 上的月份和日期查找名称对 QuerySet 进行排序。

SomeModel.objects.order_by('birth_date__month', 'birth_date__day')

对于 django >= 1.10

使用数据库函数Extract 通过annotate 方法生成额外的月份和日期列,然后order_by 这些列您可以仅按生日对QuerySet 进行排序。

from django.db.models.functions import Extract

SomeModel.objects.annotate(
    birth_date__month = Extract('birth_date', 'month'),
    birth_date__day = Extract('birth_date', 'day')
).order_by('birth_date__month', 'birth_date__day')

对于较旧的 django 版本

对于较旧的django 版本,您可以使用QuerySet.extra() 执行相同操作,但您必须编写数据库特定查询

mysql

SomeModel.objects.extra(select=
        'birth_date_month': 'MONTH(birth_date)',
        'birth_date_day': 'DAY(birth_date)'
    ,
    order_by=['birth_date_month','birth_date_day']
)

PostgreSQL

SomeModel.objects.extra(select=
        'birth_date_month': 'EXTRACT(MONTH FROM birth_date)',
        'birth_date_day': 'EXTRACT(DAY FROM birth_date)'
    ,
    order_by=['birth_date_month','birth_date_day']
)

SQlite

SomeModel.objects.extra(select=
        'birth_date_month': 'strftime("%m", birth_date)',
        'birth_date_day': 'strftime("%d", birth_date)'
    ,
    order_by=['birth_date_month','birth_date_day']
)

【讨论】:

【参考方案5】:

Post.objects.all().order_by('date_posted__minute').reverse() 其中 date_posted 是您在 Post 模型中使用的属性。

Post 只是一个示例模型

【讨论】:

您好 Janaki,感谢您的发帖!在您的答案中添加更多详细信息并使用他们使用的术语(出生月份/日期,而不是 date_posted),将帮助发布者理解您的答案,而无需他们提出后续问题。看看这个问题的其他答案,以了解需要什么。它也有助于format your code。

以上是关于按日期时间的月/日订购 Django QuerySet?的主要内容,如果未能解决你的问题,请参考以下文章

在日期时间的月、日、年...上查询 Mongodb

在日期时间的月、日、年...上查询 Mongodb

将两个给定日期之间的月、年和日计算为时间戳[重复]

Django 按日期按计数排序

订购日期从最近到最远

如何计算两个日期之间的月数和天数,而不在 SQL Server 中返回负值