Skip to main content

Display a maintenance countdown banner and block access to a Django site when the countdown expires.

Project description

django-countdown

Tests Python Version PyPI Version License

Display a maintenance countdown banner across a Django site, then block public access (returning HTTP 503) when the countdown expires. Superusers retain access during maintenance so they can finish the work and clear the countdown.

Why?

Planned downtime is the worst kind of downtime to communicate badly. Users land on a half-broken page mid-deploy, hit error logs, file support tickets, and trust erodes. django-countdown lets you announce a maintenance window before it starts (a countdown banner with a real timer), then during the window swap public traffic for an explicit "we're in maintenance" page — while leaving operators unblocked so they can actually finish the work.

Features

  • Pre-maintenance banner — an ultra-visible countdown banner inserted into templates via context processor, with a JS timer that ticks live.
  • Hard cutoff at expiry — middleware returns HTTP 503 and renders a branded blocked page once the countdown lapses.
  • Superuser bypass — admins keep working through the cutoff so they can fix the underlying issue and clear the countdown.
  • Maintenance window — optional maintenance_until lets you set a target end-time; a second banner appears for superusers and the blocked page shows a live countdown to recovery.
  • Per-Site configuration — uses Django's sites framework, so each domain in a multi-tenant setup has its own independent countdown.
  • Admin integration — full Django admin support with status colors and a validator preventing past-dated countdowns.

Supported versions

Authoritative upstream: https://docs.djangoproject.com/en/dev/faq/install/#what-python-version-can-i-use-with-django

Django 3.10 3.11 3.12 3.13 3.14 Status
5.2 LTS Active LTS (extended support Apr 2028)
6.0 Mainstream Aug 2026, extended Apr 2027

8 cells in total are exercised by the CI matrix on every push.

Installation

Using uv (recommended)

uv add django-countdown

Using pip

pip install django-countdown

Project configuration

Add to INSTALLED_APPS — the django.contrib.sites framework must also be installed:

INSTALLED_APPS = [
    # ...
    "django.contrib.sites",
    "django_countdown",
]

SITE_ID = 1

Add the blocking middleware after Django's auth middleware (it needs request.user):

MIDDLEWARE = [
    # ...
    "django.contrib.auth.middleware.AuthenticationMiddleware",
    "django_countdown.middleware.CountdownBlockingMiddleware",
]

Add the context processor so the banner partials see the active countdown:

TEMPLATES = [
    {
        # ...
        "OPTIONS": {
            "context_processors": [
                # ...
                "django_countdown.context_processors.countdown_context",
            ],
        },
    },
]

Run migrations:

./manage.py migrate

Quick start

Create a SiteCountdown row (one per django.contrib.sites.Site) via the Django admin, providing:

  • countdown_time — when access starts being blocked.
  • maintenance_until (optional) — when public access resumes.
  • message — short banner headline (max 200 chars).
  • long_description (optional) — extended copy shown on the blocked page.

The package exposes two template partials you can {% include %} from your own base layout:

{% include "django_countdown/countdown_banner.html" %}

Renders a banner before the countdown expires; switches to a subdued "maintenance in progress" banner for superusers after expiry until maintenance_until passes. Two context variables are populated by the context processor: active_countdown (pre-maintenance) and maintenance_countdown (during maintenance, superusers only).

The middleware automatically serves django_countdown/blocked.html for non-superuser requests once the countdown has expired and maintenance is ongoing.

A working end-to-end example lives under example/ — start there if you want to see the package wired up in a minimal Django project.

Optional / template-level requirements

countdown_banner.html uses {% load compress %} (from django-compressor) to bundle its CSS. If you include the banner partial in your templates, install django-compressor and add it to INSTALLED_APPS, or fork the template and drop the {% compress %} wrapping.

blocked.html references Foundation CSS and Foundation-Icons via {% static %}. If you serve those files from your project's static pipeline they will resolve; otherwise the blocked page degrades visually but still renders the maintenance message and timer.

Configuration

The package does not require any project-level Django settings. The middleware exempts /admin/, /static/, and /media/ URL prefixes from blocking by default.

Development

git clone https://github.com/iplweb/django-countdown.git
cd django-countdown
uv sync --all-extras
uv run pytest

License

MIT — see LICENSE for details.

Project details


Download files

Download the file for your platform. If you're not sure which to choose, learn more about installing packages.

Source Distribution

django_countdown-0.2.0.tar.gz (30.5 kB view details)

Uploaded Source

Built Distribution

If you're not sure about the file name format, learn more about wheel file names.

django_countdown-0.2.0-py3-none-any.whl (34.9 kB view details)

Uploaded Python 3

File details

Details for the file django_countdown-0.2.0.tar.gz.

File metadata

  • Download URL: django_countdown-0.2.0.tar.gz
  • Upload date:
  • Size: 30.5 kB
  • Tags: Source
  • Uploaded using Trusted Publishing? No
  • Uploaded via: uv/0.9.2

File hashes

Hashes for django_countdown-0.2.0.tar.gz
Algorithm Hash digest
SHA256 d87ed080bf91ab388c3a28acb046df8e56c392c483a369126166e641d625145c
MD5 ec5baaa0b078d1b447645670c0959198
BLAKE2b-256 f8cf24ef6118a39789aab8a4cf79d4e2f7e5673496bcf7961c0ce1aa465bd1b5

See more details on using hashes here.

File details

Details for the file django_countdown-0.2.0-py3-none-any.whl.

File metadata

File hashes

Hashes for django_countdown-0.2.0-py3-none-any.whl
Algorithm Hash digest
SHA256 2e5f1472348329d7970e262ad30dbc82ce3d830e0b3248ecd37bba46f7292ffe
MD5 f9e783acb410aa8c4628ce0335edbfb0
BLAKE2b-256 fcdecfdaab369f4d73cb4941be1612cae5e6f9905b1fff0ac9394ffe6f898549

See more details on using hashes here.

Supported by

AWS Cloud computing and Security Sponsor Datadog Monitoring Depot Continuous Integration Fastly CDN Google Download Analytics Pingdom Monitoring Sentry Error logging StatusPage Status page