Login

Calendar template-tag

Author:
masida
Posted:
March 23, 2007
Language:
Python
Version:
.96
Score:
23 (after 23 ratings)

Simple template tag to show a calendar. I use it to display events (which is a model with a start_date and end_date attribute. You probably should change this according to your needs.

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
# Template tag
from datetime import date, timedelta

from django import template
from myapp.models import Event # You need to change this if you like to add your own events to the calendar

register = template.Library()


from datetime import date, timedelta

def get_last_day_of_month(year, month):
    if (month == 12):
        year += 1
        month = 1
    else:
        month += 1
    return date(year, month, 1) - timedelta(1)


def month_cal(year, month):
    event_list = Event.objects.filter(start_date__year=year, start_date__month=month)

    first_day_of_month = date(year, month, 1)
    last_day_of_month = get_last_day_of_month(year, month)
    first_day_of_calendar = first_day_of_month - timedelta(first_day_of_month.weekday())
    last_day_of_calendar = last_day_of_month + timedelta(7 - last_day_of_month.weekday())

    month_cal = []
    week = []
    week_headers = []

    i = 0
    day = first_day_of_calendar
    while day <= last_day_of_calendar:
        if i < 7:
            week_headers.append(day)
        cal_day = {}
        cal_day['day'] = day
        cal_day['event'] = False
        for event in event_list:
            if day >= event.start_date.date() and day <= event.end_date.date():
                cal_day['event'] = True
        if day.month == month:
            cal_day['in_month'] = True
        else:
            cal_day['in_month'] = False  
        week.append(cal_day)
        if day.weekday() == 6:
            month_cal.append(week)
            week = []
        i += 1
        day += timedelta(1)

    return {'calendar': month_cal, 'headers': week_headers}

register.inclusion_tag('agenda/month_cal.html')(month_cal)

"""
Put this in your template (in my case agenda/month_cal.html):

<table class="cal_month_calendar">
<tr>
{% for day in headers %}
<th>{{ day|date:"D"|slice:":2" }}</hd>
{% endfor %}
</tr>
{% for week in calendar %}
<tr>
{% for day in week %}
<td{% if not day.in_month %} class="cal_not_in_month"{% endif %}>{% if day.event %}<a href="/calendar/{{ day.day|date:"Y/m" }}/">{{ day.day|date:"j" }}</a>{% else %}{{ day.day|date:"j" }}{% endif %}</td>
{% endfor %}
</tr>
{% endfor %}
</table>

"""

More like this

  1. Template tag - list punctuation for a list of items by shapiromatron 11 months, 2 weeks ago
  2. JSONRequestMiddleware adds a .json() method to your HttpRequests by cdcarter 11 months, 2 weeks ago
  3. Serializer factory with Django Rest Framework by julio 1 year, 6 months ago
  4. Image compression before saving the new model / work with JPG, PNG by Schleidens 1 year, 7 months ago
  5. Help text hyperlinks by sa2812 1 year, 7 months ago

Comments

mrben (on May 4, 2007):

I'm having problems getting this to work - I'm not entirely sure where the tag gets the year/month from. Can you help?

#

masida (on May 6, 2007):

mrben,

You can use this template tag by putting this in your template:

{% month_cal 2007 5 %}

This would render the calendar for May 2007. Of course you can use variables instead of hardcoded year/month.

Hope that helps!

#

mrben (on May 9, 2007):

Hmmm - well, things are different anyway. First I got an AttributeError from line 42 - it didn't like date() as a method of a datetime object - and now when I load it it manages to load my events page (ie the same page) in the space where the calendar should be.

I'll keep fiddling....

#

atoponce (on May 30, 2007):

I've made a couple changes to the code, that others may find useful:

def month_cal(year=date.today().year, month=date.today().month):

This will draw the calendar dynamically based on the current month and year. Thus, you can call the variable in the template with no arguments or 2:

{% month_cal %} {# current month and year #}
{% month_cal 2007 6 %} {# specific june 2007 override #}

Also, your calendar draws the beginning of the week with Monday. Some prefer Sunday. This was easy with the following code change:

first_day_of_calendar = first_day_of_month - timedelta(first_day_of_month.weekday()+1)

and

if day.weekday() == 5:

#

aronchi (on October 15, 2007):

Is it possible to view an example of the use of this?

#

f3afai (on April 3, 2008):

Can you put more instruction how to put all of the code into separate *.py files and html file, I'm new to this project

#

ludwigm (on August 1, 2008):

Change line 65 to terminate element correctly:

<th>{{ day|date:"D"|slice:":2" }}</th>

#

goober (on November 17, 2008):

Are there any updates for this snippet? Also, I tried using the templatetag and have included in my template file. For example,

{% load 129 %} {% month_cal 2008 11 %}

Can you elaborate a little bit more on the start_date and end_date attribute of the tag? Let's say, I have modified the from myapp.models import Event to party.models import Event based on the party model.

Thank you for your contribution.

#

jarofgreen (on July 26, 2009):

If you replace:

event_list = Event.objects.filter(start_date__year=year, start_date__month=month)

With:

event_list = Event.objects.filter(start_date__gte=first_day_of_calendar, start_date__lte=last_day_of_calendar)

Then appointments that are in the visible days of other months are also shown.

Or, for bonus points:

event_list = Event.objects.filter(end_date__gte=first_day_of_calendar, start_date__lte=last_day_of_calendar)

will include appointments that span multiple days

#

plungerman (on August 11, 2009):

using monthrange:

first_day_of_month = datetime.date(year, month, 1)

last_day_of_month = calendar.monthrange(year, month)

first_day_of_calendar = first_day_of_month - datetime.timedelta(first_day_of_month.weekday())

last_day_of_calendar = datetime.date(year,month,last_day_of_month[1]) + datetime.timedelta(7 - calendar.weekday(year,month,last_day_of_month[1]))

#

asinox (on August 16, 2009):

I want to know if this code will help me , i need that the user select initial date and final date from the same month of from one month to another in the same year, and in the template i need to show the 12 month's of the current year and show in different color the selected day's.... im new with Django, so i need to know if that will help me.

Thanks

#

Please login first before commenting.