【问题标题】:Django: Total birthdays each day for the next 30 daysDjango:接下来 30 天内每天的生日总数
【发布时间】:2011-08-21 16:08:54
【问题描述】:

我有一个类似的模型:

class Person(models.Model):
    name = models.CharField(max_length=40)
    birthday = DateTimeField() # their next birthday

我想获取接下来 30 天每天的总生日列表。例如,列表如下所示:

[[9, 0], [10, 3], [11, 1], [12, 1], [13, 5], ... #30 entries in list 

列表中的每个列表条目都是一个日期编号,后跟当天的生日数。例如,5 月 9 日有 0 个生日。

更新

我的数据库是 sqlite3 - 将来会迁移到 postgres。

【问题讨论】:

  • 等一下 - 生日字段是他们今年年的生日,还是他们的实际出生日期?
  • 是的,今年是他们的生日。

标签: django django-models django-queryset


【解决方案1】:
from django.db.models import Count
import datetime
today = datetime.date.today()
thirty_days = today + datetime.timedelta(days=30)
birthdays = dict(Person.objects.filter(
                    birthday__range=[today, thirty_days]
                 ).values_list('birthday').annotate(Count('birthday')))


for day in range(30):
    date = today + datetime.timedelta(day)
    print "[%s, %s]" % (date, birthdays.get(date, 0))

【讨论】:

  • 使用range字段查找绝对是要走的路。
  • 但是你不想避免aggregate吗?最后一部分是行不通的。
  • @Daniel Roseman - 这一切都适用于聚合(Count('birthday')当我添加它时它只是返回 {}。在添加之前我得到了预期的对象。
  • 因为聚合会返回一个只有 Count('birthday') 的字典
  • @zeekay @ErnieP aargh,应该是 annotate。谢谢大家。
【解决方案2】:

我会以这种方式获得天数和生日计数的列表:

from datetime import date, timedelta    
today = date.today()
thirty_days = today + timedelta(days=30)

# get everyone with a birthday
people = Person.objects.filter(birthday__range=[today, thirty_days])

birthday_counts = []
for date in [today + timedelta(x) for x in range(30)]:
    # use filter to get only birthdays on given date's day, use len to get total
    birthdays = [date.day, len(filter(lambda x: x.birthday.day == date.day, people))]
    birthday_counts.append(birthdays)

【讨论】:

  • 谢谢,虽然使用annotate 方法将计数与日期结合起来更好。你应该改用Daniel Roseman's answer
  • 但正如 Daniel 所说,他的方法不适用于 DateTime,而这正是我所拥有的。
【解决方案3】:

类似的东西--

from datetime import date, timedelta

class Person(models.Model):
    name = models.CharField(max_length=40)
    birthday = models.DateField()

    @staticmethod
    def upcoming_birthdays(days=30):
        today = date.today()
        where = 'DATE_ADD(birthday, INTERVAL (YEAR(NOW()) - YEAR(birthday)) YEAR) BETWEEN DATE(NOW()) AND DATE_ADD(NOW(), INTERVAL %S DAY)'
        birthdays = Person.objects.extra(where=where, params=[days]).values_list('birthday', flat=True)
        data = []
        for offset in range(0, days):
            i = 0
            d = today + timedelta(days=offset)
            for b in birthdays:
                if b.day == d.day and b.month == d.month:
                    i += 1
            data.append((d.day, i))
        return data

print Person.upcoming_birthdays()

【讨论】:

  • 我猜你不需要那个自定义 SQL。此外,在 Manager 上引用多个对象的函数比在 Model 中更好
【解决方案4】:

(未来 X 天生日的人的查询集) 找到了很酷的解决方案! 对我来说它有效!

from datetime import datetime, timedelta
import operator

from django.db.models import Q

def birthdays_within(days):

    now = datetime.now()
    then = now + timedelta(days)

    # Build the list of month/day tuples.
    monthdays = [(now.month, now.day)]
    while now <= then:
        monthdays.append((now.month, now.day))
        now += timedelta(days=1)

    # Tranform each into queryset keyword args.
    monthdays = (dict(zip(("birthday__month", "birthday__day"), t)) 
                 for t in monthdays)


    # Compose the djano.db.models.Q objects together for a single query.
    query = reduce(operator.or_, (Q(**d) for d in monthdays))

    # Run the query.
    return Person.objects.filter(query)

但它会得到一个在日期范围内有生日的人的列表。你应该改变一下。

【讨论】:

    猜你喜欢
    • 2018-02-01
    • 1970-01-01
    • 2015-05-21
    • 2020-06-29
    • 2022-01-15
    • 2013-05-26
    • 2016-04-20
    • 2011-09-02
    • 2014-03-29
    相关资源
    最近更新 更多