如何从具有日期时间字段的Django模型中获取每个不同的“年份”值?

时间:2012-04-18 17:58:42

标签: python django

我可以在我的Django模型中成功过滤给定年份,但我找不到列出有效年份的方法,以便用户可以访问它们。

我有一个带有定义的'datetime'字段的django模型,因此最初命名为'date'。在我的模板中,我可以成功访问'bar.date.date.year'字段,因此我知道它存在,但是当我尝试以下函数时...

blog_years=[]
for entry in blog_entries:
    if entry.date.date.year not in blog_years:
        blog_years.append(entry.date.date.year)

我被告知“'builtin_function_or_method'对象没有属性'year'”

我只能假设我嘲笑我不熟悉的Python的某些方面,但我无法弄清楚它是什么。我很确定它必须是语法,但过去那个..

7 个答案:

答案 0 :(得分:14)

Django有一种优雅而有效的方式。您可以查看他们的文档https://docs.djangoproject.com/en/1.9/ref/models/querysets/#dates 但要重温它

Entry.objects.dates('pub_date', 'year')

这将在查询中显示不同的年份值。

答案 1 :(得分:6)

如果您使用的是postgres,则可以

  BlogEntry.objects.extra(select={"year": "EXTRACT(YEAR  FROM date)"}).distinct().values_list("year", flat=True)

答案 2 :(得分:3)

第一个.date访问日期时间对象。

第二个.date正在访问datetime对象上的方法,该方法返回日期对象但不调用它(此步骤是不必要的)。

最后一部分(您编写它的方式)是尝试访问日期方法的year属性,而不是访问结果year属性日期方法调用。

更正代码以查看差异,它看起来像这样......

blog_years=[]
for entry in blog_entries:
    if entry.date.date().year not in blog_years:
        blog_years.append(entry.date.date().year)

但你应该做的更像是......

blog_years=[]
for entry in blog_entries:
    if entry.date.year not in blog_years:
        blog_years.append(entry.date.year)

因为datetime对象也有date属性。

答案 3 :(得分:3)

Python set不允许重复,所以如果你想要一份不同年份的列表:

blog_years = list(set([entry.date.year for entry in blog_entries]))

或者,您可以使用distinct()

blog_years = blog_entries.distinct(entry__date__year).values(entry__date__year)

当然,请根据您的型号调整以上内容。

答案 4 :(得分:1)

date()datetime的方法,使用

blog_years=[]
for entry in blog_entries:
    if entry.date.date().year not in blog_years:
        blog_years.append(entry.date.date().year)

答案 5 :(得分:1)

来自django 1.10它变得非常简单

foo.

答案 6 :(得分:0)

它可能不是你期望的(它可以在没有博客帖子的情况下返回几年):

from datetime import date
from django.db.models import Min

def blog_years():
    current_year = date.today().year
    queryset = Entry.objects.annotate(Min('date')).order_by('date')
    if queryset:
        oldest_year = queryset[0].date.date().year
    else:
        oldest_year = current_year
    return range(oldest_year, current_year + 1)