Jer*_*obs 7 python django django-queryset
从DateTimeField中提取年份的正确方法是什么?
给出的例子:
class Article(models.Model):
title = models.CharField(_('title'), max_length=250)
slug = models.SlugField(_('slug'), max_length=250, unique=True, default='', blank=True)
content = models.TextField(_('content'))
author = models.ForeignKey(settings.AUTH_USER_MODEL)
categories = models.ManyToManyField(Category)
tags = models.ManyToManyField(Tag)
created = models.DateTimeField(_('created'), default=timezone.now)
publish_date = models.DateTimeField(_('publish date'), blank=True, null=True)
STATUS_ARTICLE = (
('DRAFT', _('draft')),
('PUBLISHED', _('published'))
)
status = models.CharField(_('status'), max_length=100, choices=STATUS_ARTICLE, default='DRAFT')
class ExtractMonth(Func):
template = "EXTRACT(MONTH FROM %(expressions)s)"
def __init__(self, *expressions, **extra):
extra['output_field'] = models.SmallIntegerField()
super().__init__(*expressions, **extra)
Run Code Online (Sandbox Code Playgroud)
试图获取所有年份的列表,以及每年的文章数量:
result = Article.objects.filter(status='PUBLISHED').annotate(Year=ExtractYear('publish_date')).values('Year').annotate(dcount=Count('Year'))
Run Code Online (Sandbox Code Playgroud)
这会导致以下错误:
near "FROM": syntax error
Run Code Online (Sandbox Code Playgroud)
生成的查询是:
SELECT EXTRACT(YEAR FROM "articles_article"."publish_date") AS "Year", COUNT(EXTRACT(YEAR FROM "articles_article"."publish_date")) AS "dcount" FROM "articles_article" WHERE "articles_article"."status" = PUBLISHED GROUP BY EXTRACT(YEAR FROM "articles_article"."publish_date"), "articles_article"."created" ORDER BY "articles_article"."created" DESC
Run Code Online (Sandbox Code Playgroud)
我发现这个问题很有趣。所以我用控制台玩了一段时间。
我按照@Ivan 提供的链接得到了这个:
from django.db.models import F, Func
from django.db.models.functions import Substr
Article.objects.filter(...).annotate(_date=Func(F('publish_date'), function='LOWER'))
.annotate(publish_year=Substr('_date', 1, 4))
.values('publish_year')
Run Code Online (Sandbox Code Playgroud)
这应该以字符串形式给出您的年份。
注意:如果_date您得到类似这样的内容,这将起作用:u'2015-08-24 09:45:16'如果您得到不同的字符串,则可以更改 中的索引Substr('_date', 1, 4)。_date您可以通过将其添加到 中来查看您获得的字符串类型.values('_date', 'publish_year')。
我希望这有帮助。
额外的:
这是我得到的结果:
[{'date': datetime.datetime(2015, 8, 24, 9, 45, 16), 'date3': u'2015', 'date2': u'2015-08-24 09:45:16'}, ...]
Run Code Online (Sandbox Code Playgroud)
在这种情况下,date3对我来说就是最终的结果。
编辑:
生成的SQL:
>>> print MyModel.objects.all().annotate(date2=Func(F('date'), function='LOWER')).annotate(date3=Substr('date2', 1, 4)).query
SELECT `app_model`.`id`, `app_model`.`date`, LOWER(`app_model`.`date`)
AS `date2`, SUBSTRING(LOWER(`app_model`.`date`), 1, 4)
AS `date3` FROM `app_model` ORDER BY `app_model`.`created` ASC
Run Code Online (Sandbox Code Playgroud)
| 归档时间: |
|
| 查看次数: |
2659 次 |
| 最近记录: |