按日期时间的月/日订购 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() 执行相同操作,但您必须编写数据库特定查询。
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?的主要内容,如果未能解决你的问题,请参考以下文章