如何在 Django 中组合查询集来显示日历事件?

How to combine querysets in Django to show calendar events?

我正在尝试创建一个日历,如果在 Event 模型中创建了事件以及 DateTimeField

,则在日期下方显示事件

这是我的代码: views.py

from django.shortcuts import render
import calendar

from .models import Event

def Cal(request, year, month):
    calendar.setfirstweekday(calendar.SUNDAY)
    prev_year = int(year)
    next_year = int(year)
    prev_month = int(month) - 1
    next_month = int(month) + 1
    if prev_month == 0:
        prev_year -= 1
        prev_month = 12
    if next_month == 13:
        next_year += 1
        next_month = 1
    month_cal = calendar.monthcalendar(int(year), int(month))
    events = Event.objects.filter(when__year=year, when__month=month)
    return render(request, "cal/calendar.html", {
                                                "month_cal": month_cal,
                                                "prev_month": prev_month,
                                                "next_month": next_month,
                                                "prev_year": prev_year,
                                                "next_year": next_year,
                                                "events": events,
                                            })

calendar.html

{% extends "base.html" %}

{% block body %}
<table border="1" cellspacing="0" cellpadding="10" width="40%" height="80%">
    <tr>
        <td>Sun</td>
        <td>Mon</td>
        <td>Tue</td>
        <td>Wed</td>
        <td>Thu</td>
        <td>Fri</td>
        <td>Sat</td>
    </tr>
    {% for week in month_cal %}
        <tr>
        {% for day in week %}
            <td>
                {% if day == 0 %}
                    -
                    {% else %}
                    {{ day }}
                    {% endif %}
            </td>
            {% endfor %}
        </tr>
    {% endfor %}
</table>


<a href="{% url 'calendar:calendar' prev_year prev_month %}">previous</a>
<a href="{% url 'calendar:calendar' next_year next_month %}">next</a>
{% endblock %}

我能够成功地遍历所有事件并遍历日历中的所有日期。但是,我希望事件在适当的日期显示在日历中。

我建议在您的上下文中添加 {day_of_month: events} 的映射,而不是整个月所有事件的列表。这样,在构建模板时,您无需遍历每个月的每一天的所有事件。

这是一个示例实现:

views.py

from collections import defaultdict

...

def Cal(request, year, month):

    ...

    events = Event.objects.filter(when__year=year, when__month=month)
    event_days = defaultdict(list)
    for event in events:
        event_days[event.when.day].append(event)
    return render(request, "cal/calendar.html", {
                                            "month_cal": month_cal,
                                            "prev_month": prev_month,
                                            "next_month": next_month,
                                            "prev_year": prev_year,
                                            "next_year": next_year,
                                            "event_days": event_days,
                                        })

接下来,您需要 include a dict lookup template filter 在您的项目中。 (有关实施,请参阅相关问题。)

现在,当您循环浏览日历时,您可以轻松地按天访问事件:

calendar.html

...

{% for week in month_cal %}
    <tr>
    {% for day in week %}
        <td>
            {% if day == 0 %}
                -
            {% else %}
                {{ day }}
                {% for event in event_days|get_item:day %}
                    {# format the event here #}
                    {{ event.description }} 
                {% endfor %}
            {% endif %}
        </td>
        {% endfor %}
    </tr>
{% endfor %}

...