Jeg har lavet endnu et Django-eksperiment med https://ugenr.dk som det store forbillede.

På https://wallnot.dk/kalender kan du altid finde en Mayland-style-kalender med helligdage og ugenumre. Kalenderen understøtter år 1 til 9999.
Den er lavet med tre side-funktioner: En der altid viser nuværende halvår (kalindex), en der viser et hvilket som helst halvår (kalperiod) og en der kan vise et hvilket som helst år (kalyear). Alle tre funktioner kalder en fjerde funktion get-dates der returnerer datoer i kalenderen for det år og/eller halvår, der efterspørges.
Her er views.py:
from django.shortcuts import render
import datetime
from workalendar.europe import Denmark # Module containing most Danish holidays
from django.http import Http404
# Function to return all calendar dates and other context data
def get_dates(year, period, now):
now_isocalendar = now.isocalendar()
### HOLIDAY LIST FOR YEAR IS GENERATED ###
# Create dictionary with all holidays of the year
holidays = Denmark().holidays(year)
all_holidays = {}
all_holidays[datetime.date(year,5,1)] = ["Første maj", "Særlig dag"]
all_holidays[datetime.date(year,6,5)] = ["Grundlovsdag", "Særlig dag"]
all_holidays[datetime.date(year,12,31)] = ["Nytårsaften", "Særlig dag"]
holiday_lookup = {
"New year": ["Nytårsdag", "Helligdag"],
"Holy Thursday": ["Skærtorsdag", "Helligdag"],
"Good Friday": ["Langfredag", "Helligdag"],
"Easter Sunday": ["Påskedag", "Helligdag"],
"Easter Monday": ["2. påskedag", "Helligdag"],
"Store Bededag": ["Store bededag", "Helligdag"],
"Ascension Thursday": ["Kr. himmelfart", "Helligdag"],
"Pentecost Sunday": ["Pinsedag", "Helligdag"],
"Pentecost Monday": ["2. pinsedag", "Helligdag"],
"Christmas Eve": ["Juleaften", "Særlig dag"],
"Christmas Day": ["1. juledag", "Helligdag"],
"Second Day of Christmas": ["2. juledag", "Helligdag"],
}
for holiday in holidays:
# Check for two holidays on same day
if holiday[0] not in all_holidays:
all_holidays[holiday[0]] = (holiday_lookup[holiday[1]][0], holiday_lookup[holiday[1]][1])
# If two on the same day, names are concenated
else:
all_holidays[holiday[0]] = (holiday_lookup[holiday[1]][0] + "/" + all_holidays[holiday[0]][0] , holiday_lookup[holiday[1]][1])
### DATES FOR YEAR ARE GENERATED IN A DAY AND MONTH DIMENSION ###
# First dimension is maximum number of days in a month
dates_in_year = {}
for day in range(1,32):
dates_in_year[day] = []
# Second dimension is that date for each month
for day in range(1,32):
for month in period:
# If the generated day actually is a valid date, day is added to dates_in_year dictionary
try:
date_to_add = datetime.date(year,month,day)
date_isocalendar = date_to_add.isocalendar()
# HOLIDAY LOGIC #
# If day is special, get type of day and name of day
if date_to_add in all_holidays:
type_of_day = all_holidays[date_to_add][1]
name_of_day = all_holidays[date_to_add][0]
# If not, type of day is normal and no name
else:
type_of_day = "Normal dag"
name_of_day = "Intet navn"
# HTML BORDER CLASS LOGIC #
html_class = ""
# Year of date must be the same as year of current date
if date_isocalendar[0] == now_isocalendar[0]:
# Week number is the same as current week number
if date_isocalendar[1] == now_isocalendar[1]:
# All days get a red right and red left class
html_class = "redleft redright"
# Sunday also gets a red bottom class
if date_isocalendar[2] == 7:
html_class += " redbottom"
# Date is Sunday in the week before current
elif date_isocalendar[1] == now_isocalendar[1] - 1 and date_isocalendar[2] == 7:
html_class += " redbottom"
# Same date next month is in current week
try:
date_next_month = datetime.date(year,month + 1,day)
date_next_month_isocalendar = date_next_month.isocalendar()
# Week number is the same as current week number
if date_next_month_isocalendar[1] == now_isocalendar[1]:
html_class = "redright"
except ValueError:
pass
date_data = (date_to_add, type_of_day, name_of_day, html_class)
dates_in_year[day].append(date_data)
# Except when that dates does not exist, e.g. february 30
except ValueError:
dates_in_year[day].append("NON-EXISTING DATE")
context = {'year': str(year), 'next': year+1, 'previous': year-1, 'dates_in_year': dates_in_year, 'period': period, 'now': now}
return context
# Main page
def kalindex(request):
now = datetime.datetime.now()
year = now.year
month = now.month
if month < 7:
period = range(1,7)
else:
period = range(7,13)
# Run function to get calendar dates
context = get_dates(year, period, now)
return render(request, 'kalender/index.html', context)
# Earlier or future year page
def kalyear(request, year):
# If year is not an integer, a 404 error is thrown
try:
year = int(year)
except ValueError:
raise Http404
# If year is between 1 and 10000, a calendar is rendered
if year > 0 and year < 10000:
now = datetime.datetime.now()
period = range(1,13)
# Run function to get calendar dates
context = get_dates(year, period, now)
return render(request, 'kalender/index.html', context)
# If not, a 404 error is thrown
else:
raise Http404
# Earlier or future year page
def kalperiod(request, year, period):
# If year is not an integer, a 404 error is thrown
try:
year = int(year)
except ValueError:
raise Http404
# If year is between 1 and 10000, a calendar is rendered
if year > 0 and year < 10000 and (period == "1" or period == "2"):
if period == "1":
period = range(1,7)
elif period == "2":
period = range(7,13)
now = datetime.datetime.now()
# Run function to get calendar dates
context = get_dates(year, period, now)
return render(request, 'kalender/index.html', context)
# If not, a 404 error is thrown
else:
raise Http404
Sidens skabelon index.html ser en lille smule rodet ud (af hensyn til at minimere sidens størrelse). Skabelonen genererer en tabel ved at gennemgå alle dagene i kalenderen og tilføje særlige layout-regler for lørdage, søndage, helligdage, den nuværende uge, dag og ugenummer osv.
Her er den del af den, der benytter sig af Djangos skabelon-funktioner. (Resten af koden kan du finde ved at bruge “view source” på https://wallnot.dk/kalender):
{% if period|length == 12 %}
{% if not year == "1" %}<a href="{% url 'kal_year' previous %}" title="Se kalender for året før">« forrige</a>{% endif %}<h1> Kalender for år {{ year }} </h1>{% if not year == "9999" %}<a href="{% url 'kal_year' next %}" title="Se kalender for året efter">næste »</a>{% endif %} <a class="calendartype" href="{% if now|date:"n" == "7" or now|date:"n" == "8" or now|date:"n" == "9" or now|date:"n" == "9" or now|date:"n" == "10" or now|date:"n" == "11" or now|date:"n" == "12" and now|date:"Y" == year %}{% url 'kal_period' year 2 %}{% else %}{% url 'kal_period' year 1 %}{% endif %}" title="Gå til halvårskalender">Til halvårskalender</a>
{% elif period|last == 6 %}
{% if not year == "1" %}<a href="{% url 'kal_period' previous 2 %}" title="Se kalender for halvåret før">« forrige </a>{% endif %}<h1> Kalender for år {{ year }}, første halvår </h1><a href="{% url 'kal_period' year 2 %}" title="Se kalender for halvåret efter">næste »</a> <a class="calendartype" href="{% url 'kal_year' year %}" title="Gå til helårskalender">Til helårskalender</a>
{% else %}
<a href="{% url 'kal_period' year 1 %}" title="Se kalender for halvåret før">« forrige</a><h1> Kalender for år {{ year }}, andet halvår </h1>{% if not year == "9999" %}<a href="{% url 'kal_period' next 1 %}" title="Se kalender for halvåret efter">næste »</a>{% endif %} <a class="calendartype" href="{% url 'kal_year' year %}" title="Gå til helårskalender">Til helårskalender</a>
{% endif %}
<p>I dag er det {{ now|date:"l" }} den {{ now|date }} i uge {{ now|date:"W" }}</p>
<table>
<thead>
<tr>
{% if period|length == 12 %}
<th>Januar</th>
<th>Februar</th>
<th>Marts</th>
<th>April</th>
<th>Maj</th>
<th>Juni</th>
<th>Juli</th>
<th>August</th>
<th>September</th>
<th>Oktober</th>
<th>November</th>
<th>December</th>
{% elif period|last == 6 %}
<th>Januar</th>
<th>Februar</th>
<th>Marts</th>
<th>April</th>
<th>Maj</th>
<th>Juni</th>
{% else %}
<th>Juli</th>
<th>August</th>
<th>September</th>
<th>Oktober</th>
<th>November</th>
<th>December</th>
{% endif %}
</tr>
</thead>
<tbody>
{% for month, monthdays in dates_in_year.items %}
<tr>
{% for day in monthdays %}
<td{% if day.1 == "Helligdag" or day.0|date:"w" == "0" %} class="holy{% if day.3 %} {{ day.3 }}{% endif %}"{% elif day == "NON-EXISTING DATE" %} class="noborder"{% elif year == now|date:"Y" and day.3 %} class="{{ day.3 }}"{% endif %}>
<div title="{{ day.0|date:"l"|capfirst }}" class="weekday{% if day.0|date:"w" == "6" %} saturday{% endif %}{% if day.0|date == now|date %} red{% endif %}">{{ day.0|date:"D"|slice:":1"|upper }}</div>
<div class="datenum{% if day.0|date:"w" == "6" %} saturday{% endif %}{% if day.0|date == now|date %} red{% endif %}">{{ day.0|date:"j" }}</div>
{% if day.0|date:"w" == "1" %}<div title="Uge {{ day.0|date:"W" }}" class="weeknum{% if day.0|date:"Y W" == now|date:"Y W" %} red{% endif %}">{{ day.0|date:"W" }}</div>{% endif %}
{% if day.1 == "Helligdag" or day.1 == "Særlig dag" %}<div title="{{ day.2 }}" class="named{% if "/" in day.2 and period|length == 12 %} named-small{% endif %}{% if day.0|date == now|date %} red{% endif %}">{{ day.2 }}</div>{% endif %}
</td>
{% endfor %}
</tr>
{% endfor %}
</tbody>
</table>