6

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

我有一个 django 模型,其中定义了“日期时间”字段,哦,原来命名为“日期”。在我的模板中,我可以成功访问“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 的某些方面,但我无法弄清楚它是什么。我很确定它必须是语法的,但除此之外......

4

7 回答 7

24

Django 有一种优雅而有效的方式来做到这一点。您可以从他们的文档中查看https://docs.djangoproject.com/en/3.0/ref/models/querysets/#dates 但要仔细阅读

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

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

于 2016-04-18T16:18:32.333 回答
6

如果您使用的是 postgres,您可以这样做

  BlogEntry.objects.extra(select={"year": "EXTRACT(YEAR FROM date)"}).distinct().values_list("year", flat=True)
于 2014-04-03T21:42:48.700 回答
5

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

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)

当然,根据您的模型调整上述内容。

于 2012-10-27T14:55:29.347 回答
3

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

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

最后一部分(您编写它的方式)是尝试访问yeardate 方法的属性,而不是访问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)

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

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

因为 datetime 对象也有 date 属性。

于 2012-04-18T18:02:34.487 回答
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)
于 2012-04-18T18:02:45.310 回答
1

从 django 1.10 开始,它变得非常简单

from django.db.models.functions import ExtractYear 

blog_years= blog_entries.annotate(
      year=ExtractYear('created_on')
).values_list('year', flat=True)
blog_years = sorted(set(blog_years), reverse=True)
于 2017-11-04T04:19:30.213 回答
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)
于 2012-10-27T14:46:31.720 回答