repos
/ analytics-django master

analytics-django

mirror archived upstream

Self-hostable website analytics on Django: a straightforward collector API, dashboards, a world map, and PDF reports.

analyticsdjangodockerhandcodedpythonself-hostedsqliteviteweb-analytics

4.0 KB · 151 lines · Python Raw History
  1import os
  2from pathlib import Path
  3
  4from django.contrib.messages import constants as messages
  5
  6
  7# Build paths inside the project like this: BASE_DIR / 'subdir'.
  8BASE_DIR = Path(__file__).resolve().parent.parent.parent
  9
 10
 11# Application definition
 12
 13INSTALLED_APPS = [
 14    'django.contrib.admin',
 15    'django.contrib.auth',
 16    'django.contrib.contenttypes',
 17    'django.contrib.sessions',
 18    'django.contrib.messages',
 19    'django.contrib.staticfiles',
 20
 21    'accounts',
 22    'properties',
 23    'collector',
 24    'pages',
 25]
 26
 27MIDDLEWARE = [
 28    'django.middleware.security.SecurityMiddleware',
 29
 30    'whitenoise.middleware.WhiteNoiseMiddleware',
 31
 32    'django.contrib.sessions.middleware.SessionMiddleware',
 33    'django.middleware.common.CommonMiddleware',
 34    'django.middleware.csrf.CsrfViewMiddleware',
 35    'django.contrib.auth.middleware.AuthenticationMiddleware',
 36    'django.contrib.messages.middleware.MessageMiddleware',
 37    'django.middleware.clickjacking.XFrameOptionsMiddleware',
 38]
 39
 40ROOT_URLCONF = 'analytics.urls'
 41
 42TEMPLATES = [
 43    {
 44        'BACKEND': 'django.template.backends.django.DjangoTemplates',
 45        'DIRS': [BASE_DIR / 'analytics/templates'],
 46        'APP_DIRS': True,
 47        'OPTIONS': {
 48            'context_processors': [
 49                'django.template.context_processors.debug',
 50                'django.template.context_processors.request',
 51                'django.contrib.auth.context_processors.auth',
 52                'django.contrib.messages.context_processors.messages',
 53
 54                'analytics.context_processors.collector',
 55                'analytics.context_processors.canonical',
 56                'analytics.context_processors.base_url',
 57            ],
 58        },
 59    },
 60]
 61
 62WSGI_APPLICATION = 'analytics.wsgi.application'
 63
 64
 65# Messages
 66# https://docs.djangoproject.com/en/3.0/ref/settings/#messages
 67
 68MESSAGE_TAGS = {
 69    messages.DEBUG: "alert-info",
 70    messages.INFO: "alert-info",
 71    messages.SUCCESS: "alert-success",
 72    messages.WARNING: "alert-warning",
 73    messages.ERROR: "alert-danger",
 74}
 75
 76
 77# Internationalization
 78# https://docs.djangoproject.com/en/4.0/topics/i18n/
 79
 80LANGUAGE_CODE = 'en-us'
 81TIME_ZONE = 'UTC'
 82USE_I18N = True
 83USE_TZ = True
 84USE_THOUSAND_SEPARATOR = True
 85
 86
 87# Static files (CSS, JavaScript, Images)
 88# https://docs.djangoproject.com/en/4.0/howto/static-files/
 89
 90STATIC_URL = 'static/'
 91STATICFILES_STORAGE = "whitenoise.storage.CompressedManifestStaticFilesStorage"
 92STATICFILES_DIRS = (
 93    BASE_DIR / "analytics/static",
 94    BASE_DIR / "analytics/static_maps",
 95)
 96STATIC_ROOT = BASE_DIR / "static"
 97
 98
 99# Media files (Images, Videos)
100# https://docs.djangoproject.com/en/4.0/ref/settings/#media-root
101
102MEDIA_URL = 'media/'
103MEDIA_ROOT = BASE_DIR / "media"
104
105
106# Database
107# https://docs.djangoproject.com/en/4.0/ref/settings/#databases
108
109DATABASES = {
110    'default': {
111        'ENGINE': 'django.db.backends.sqlite3',
112        'NAME': BASE_DIR / 'db.sqlite3',
113        'OPTIONS': {
114            'timeout': 30,
115            'transaction_mode': 'IMMEDIATE',
116            # mmap_size is intentionally omitted: gunicorn workers each open
117            # their own connection, and SQLite's mmap is documented as unsafe
118            # for multi-process writers — it amplified an unrelated WAL
119            # inconsistency into full database corruption in the status repo
120            # on 2026-04-19.
121            'init_command': (
122                'PRAGMA journal_mode=WAL;'
123                'PRAGMA synchronous=NORMAL;'
124                'PRAGMA foreign_keys=ON;'
125                'PRAGMA temp_store=MEMORY;'
126                'PRAGMA journal_size_limit=67108864;'
127                'PRAGMA cache_size=-20000;'
128            ),
129        },
130    }
131}
132
133
134# Default primary key field type
135# https://docs.djangoproject.com/en/4.0/ref/settings/#default-auto-field
136
137DEFAULT_AUTO_FIELD = 'django.db.models.BigAutoField'
138
139
140# Auth
141# https://docs.djangoproject.com/en/3.0/ref/settings/#auth
142
143AUTH_USER_MODEL = "accounts.User"
144LOGIN_REDIRECT_URL = "properties"
145
146
147# Email
148# https://docs.djangoproject.com/en/4.0/topics/email/#console-backend
149
150EMAIL_BACKEND = 'django.core.mail.backends.console.EmailBackend'