在接下来的X天内有生日的人的查询集

3 投票
6 回答
3464 浏览
提问于 2025-04-16 18:20

我想知道怎么获取在接下来X天内过生日的人的列表。我看到过这个答案,但对我来说不太合适,因为它只获取了当前年份出生的人。

6 个回答

1

假设这是一个日期时间字段,可以像这样做(使用dimosaur的答案中的future_date):

Profile.objects.get(
    Q(birthday__lte=future_date),
    Q(birthday__gte=datetime.date.today())
)
1

我能想到两种方法,不用自定义查询,但都有一些“问题”。

1) 效率不高,因为每天只进行一次查询。

start = datetime.date.today()
max_days = 14
days = [ start + datetime.timedelta(days=i) for i in xrange(0, max_days) ]

birthdays = []
for d in days:
    for p in Profile.objects.filter(birthday__month=d.month, birthday__day=d.day):
        birthdays.append(p)

print birthdays

2) 只需要一次查询,但需要对模型进行修改。你需要添加两个整数字段,分别是 bday_month 和 bday_day。这些字段可以从真实的日期自动填充。

这个例子的限制在于,你只能检查两个特定的月份,起始月份和结束月份。如果设置为29天,你可能会跳过二月份,只显示1月31日和3月1日。

from django.db.models import Q    
start = datetime.date.today()
end = start + datetime.timedelta(days=14)

print Profile.objects.filter(
    Q(bday_month=start.month) & Q(bday_day__gte=start.day) | 
    Q(bday_month=end.month) & Q(bday_day__lte=end.day)
)
13

假设我们有这样的一个模型--

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

下一步就是创建一个查询,过滤掉那些生日在某个范围内的记录,也就是在现在的月份和日期(now.month, now.day)与某个特定的月份和日期(then.month, then.day)之间的。你可以通过查询集的API来访问日期时间对象的月份和日期,比如用这样的关键字参数: "birthday__month"。我尝试过用一个实际的查询集API方法,比如 "birthday__month__gte",但是没有成功。所以我建议你可以直接生成一个包含每个(月份,日期)元组的列表,这些元组代表你想要记录的日期范围,然后把它们组合成一个查询,使用django.db.models.Q,像这样:

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)

经过调试后,这个查询应该会返回一个查询集,里面包含每个生日的月份和日期与指定的元组列表中的任何月份或日期相等的人。

撰写回答