This piece of software started out as a simple tool to assist in creating readable timetables for NTNU courses. The earliest version of the site provided this functionality and nothing more. As more fellow students started using the software new features where added based on personal needs and suggestions from other students.
- Simple interface for adding courses.
- Customizable view of your timetable.
- Easy export to Google-Calendar via iCal.
- PDF-version for printing.
- User defined deadlines.
- Import of course data from ntnu.no or database-dumps.
- python3-django
- python3-django-compressor
- python3-lxml
- python3-psycopg2
- python3-pylibmc
- python3-reportlab
- python3-requests
- python3-sentry-sdk
- python3-sphinx
- python3-tqdm
- python3-vobject
The app supports a few request modifiers that affect caching, conditional responses, language selection, and debug rendering.
?no-cache- Bypasses internal response cache reads in views that call
plan.common.utils.should_bypass_cache. - Currently applies to schedule HTML and iCal views.
- Bypasses internal response cache reads in views that call
Cache-Control: no-cache- Same bypass behavior as
?no-cachefor views usingshould_bypass_cache.
- Same bypass behavior as
Pragma: no-cache- Same bypass behavior as
?no-cachefor views usingshould_bypass_cache.
- Same bypass behavior as
?no-modified-since- Disables
If-Modified-Since/Last-Modifiedshort-circuiting incheck_modified_since. - Does not disable ETag/
If-None-Matchhandling.
- Disables
?debug- Only active when
DEBUG=True. - Enables
text_debug_middleware, which converts non-HTML responses to debug-friendly HTML output.
- Only active when
no-cacheis a response-cache bypass, not a full data-cache bypass.- It bypasses rendered response/view caches (for example schedule HTML and iCal response cache lookups).
- It does not automatically bypass lower-level caches such as schedule/data/DB-derived caches unless a specific code path forwards a separate bypass flag.
- Conditional
304 Not Modifiedresponses may still be returned first if ETag/conditional headers match.
- Locale middleware currently interprets the raw query string as the language
code (for example
?nb), not key/value pairs like?lang=nb.
Use unified settings for runserver. nix develop sets local data, cache, and Postgres socket paths:
DJANGO_SETTINGS_MODULE=plan.settingsDJANGO_DEBUG=trueDJANGO_DEBUG_TOOLBAR=1to enable Django Debug ToolbarPLAN_BASE_DIR=...to change the defaultdata/directory
Offline mode prep (once after static/template changes):
./manage.py collectstatic --noinput
DJANGO_COMPRESS_ENABLED=true DJANGO_COMPRESS_OFFLINE=true ./manage.py compress --forceRunserver against helper DB:
nix develop
run-dbIn another shell:
nix develop
./manage.py migrate
./manage.py runserverUse the helper in the dev shell. It loads the Nix image, uses host networking,
runs as your current user, and connects to the run-db Unix socket in
data/pgdata. It uses data/cache for Django file cache.
nix develop
run-dbIn another shell:
nix develop
run-containerUse Podman instead of Docker:
run-container --podman