Settings
All settings live in config/settings.py. Buraq reads them at startup via the settings_module argument passed to Buraq(settings_module="config.settings").
Core settings
Section titled “Core settings”Core settings
Section titled “Core settings”from pathlib import Path
BASE_DIR = Path(__file__).resolve().parent.parent
# SECURITYSECRET_KEY = "change-me-in-production"DEBUG = TrueALLOWED_HOSTS = ["*"]
# APPSINSTALLED_APPS = [ "buraq.contrib.auth", "posts",]
# DATABASEDATABASE_URL = "sqlite+aiosqlite:///./db.sqlite3"
# TEMPLATESTEMPLATES_DIR = str(BASE_DIR / "templates") # one path, or a list of themAPP_DIRS = True # also search each installed app's templates/
# Anything Jinja's Environment accepts. "undefined" and "extensions" take# dotted paths so this file never has to import jinja2; everything else is# passed straight through.TEMPLATE_OPTIONS = { "undefined": "jinja2.StrictUndefined", # a typo raises instead of rendering "" "trim_blocks": True, "extensions": ["jinja2.ext.loopcontrols"], # enables {% break %} / {% continue %}}
# STATIC FILESSERVE_STATIC = True # False for an API, or when a # web server in front serves filesSTATIC_URL = "/static/"STATIC_ROOT = str(BASE_DIR / "staticfiles") # destination for collectstaticSTATICFILES_DIRS = [str(BASE_DIR / "static")] # source directories
# Storage backend — ManifestStaticFilesStorage adds content-hashed filenamesSTATICFILES_STORAGE = "buraq.contrib.staticfiles.storage.StaticFilesStorage"
# MEDIAMEDIA_DIR = str(BASE_DIR / "media")MEDIA_URL = "/media/"Database
Section titled “Database”Database
Section titled “Database”# SQLite (development)DATABASE_URL = "sqlite+aiosqlite:///./db.sqlite3"
# PostgreSQL (production)DATABASE_URL = "postgresql+asyncpg://user:password@localhost:5432/mydb"
# MySQLDATABASE_URL = "mysql+aiomysql://user:password@localhost:3306/mydb"The driver is named in the scheme — +aiosqlite, +asyncpg, +aiomysql — and
it has to be an async one. Leaving it out, or naming a blocking driver, is
refused at startup:
ImproperlyConfigured: DATABASE_URL is 'postgresql', which selects a blockingdriver. Buraq is async throughout, so the driver has to be one that can beawaited.
Use: postgresql+asyncpg://...
Install it with: pip install buraq[postgres]Left to SQLAlchemy this surfaces as ModuleNotFoundError: No module named 'psycopg2', which reads like a missing dependency and is not — installing
psycopg2 cannot help, because it cannot be awaited.
More than one database
Section titled “More than one database”DATABASE_URL is one connection. To use several, name them:
DATABASES = { "default": "postgresql+asyncpg://user:pass@primary/db", "replica": "postgresql+asyncpg://user:pass@replica/db",}DATABASE_READ_REPLICAS = ["replica"]default is required — every query that does not name a database uses it.
DATABASE_READ_REPLICAS lists the aliases reads may be sent to, in rotation.
Writes always go to default, and so do reads inside atomic().
Setting DATABASES replaces DATABASE_URL; a project needs one or the other,
not both.
See Reading from a replica
for what routes where, and using().
URL handling
Section titled “URL handling”ROOT_URLCONF = "config.urls" # dotted path to the URLconf moduleAPPEND_SLASH = True # redirect /posts to /posts/ when it matchesPREPEND_WWW = False # redirect example.com to www.example.comNumber formatting
Section titled “Number formatting”NUMBER_GROUPING = 3 # digits per groupDECIMAL_SEPARATOR = "."THOUSAND_SEPARATOR = ","DATABASE_ECHO
Section titled “DATABASE_ECHO”Log every SQL statement the engine emits. Off by default; turn it on while debugging a query, not in normal development, since it prints during management commands too.
DATABASE_ECHO = True# In-memory (default, single-process only)CACHE_BACKEND = "buraq.contrib.cache.backends.memory.MemoryCacheBackend"
# Redis (recommended for production)CACHE_BACKEND = "buraq.contrib.cache.backends.redis.RedisCacheBackend"CACHE_REDIS_URL = "redis://localhost:6379/0"
# MemcachedCACHE_BACKEND = "buraq.contrib.cache.backends.memcached.MemcachedCacheBackend"CACHE_MEMCACHED_URL = "memcached://localhost:11211"
# FileCACHE_BACKEND = "buraq.contrib.cache.backends.file.FileCacheBackend"CACHE_FILE_PATH = "/tmp/buraq_cache"
# Shared optionsCACHE_KEY_PREFIX = "myapp:"CACHE_DEFAULT_TIMEOUT = 300 # secondsEMAIL_BACKEND = "buraq.contrib.email.backends.smtp.SMTPEmailBackend"EMAIL_HOST = "smtp.gmail.com"EMAIL_PORT = 587EMAIL_USE_TLS = TrueEMAIL_HOST_USER = "you@gmail.com"EMAIL_HOST_PASSWORD = "your-app-password"DEFAULT_FROM_EMAIL = "you@gmail.com"
# During development — write emails to disk instead of sendingEMAIL_BACKEND = "buraq.contrib.email.backends.file.FileEmailBackend"EMAIL_FILE_PATH = "./sent_emails"Multiple Mailers
Section titled “Multiple Mailers”# Named email backends — select with send_mail(..., using="transactional")MAILERS = { "transactional": { "BACKEND": "buraq.contrib.email.backends.smtp.SMTPEmailBackend", "HOST": "smtp.sendgrid.net", "PORT": 587, "HOST_USER": "apikey", "HOST_PASSWORD": "SG.xxx", "USE_TLS": True, }, "bulk": { "BACKEND": "buraq.contrib.email.backends.smtp.SMTPEmailBackend", "HOST": "bulk.mailrelay.com", "PORT": 587, "HOST_USER": "bulk@example.com", "HOST_PASSWORD": "secret", "USE_TLS": True, },}Security
Section titled “Security”Security headers
Section titled “Security headers”Configured via buraq.middleware.SecurityMiddleware:
# HTTPS redirectSECURE_SSL_REDIRECT = True # redirect all HTTP → HTTPS (default: False)
# HSTSSECURE_HSTS_SECONDS = 31536000 # 1 yearSECURE_HSTS_INCLUDE_SUBDOMAINS = TrueSECURE_HSTS_PRELOAD = True
# Other headers (all True/set by default)SECURE_CONTENT_TYPE_NOSNIFF = True # X-Content-Type-Options: nosniffSECURE_REFERRER_POLICY = "same-origin" # Referrer-PolicySECURE_CROSS_ORIGIN_OPENER_POLICY = "same-origin" # COOPX_FRAME_OPTIONS = "SAMEORIGIN" # X-Frame-Options
# Permissions-Policy (empty by default — add what you need)SECURE_PERMISSIONS_POLICY = { "geolocation": "()", "microphone": "()", "camera": "()",}See Security Middleware for setup instructions.
CORS_ORIGINS = ["https://myfrontend.com"]CORS_ALLOW_CREDENTIALS = TrueCORS_ALLOW_METHODS = ["GET", "POST", "PUT", "PATCH", "DELETE", "OPTIONS"]CORS_ALLOW_HEADERS = ["*"]Authentication and sessions
Section titled “Authentication and sessions”Authentication
Section titled “Authentication”SECRET_KEY = "your-jwt-secret-key"JWT_ALGORITHM = "HS256"JWT_EXPIRY_MINUTES = 60
# Custom user model — dotted path to your User model class# Default: "buraq.contrib.auth.models.User"AUTH_USER_MODEL = "myapp.models.MyUser"
# How long (in seconds) password-reset links remain valid# Default: 259200 (3 days)PASSWORD_RESET_TIMEOUT = 259200Password validators
Section titled “Password validators”Control which password-strength rules are enforced on registration and password-change:
AUTH_PASSWORD_VALIDATORS = [ # Minimum 8 characters (default) {"NAME": "buraq.contrib.auth.password_validation.MinimumLengthValidator"},
# Custom minimum length {"NAME": "buraq.contrib.auth.password_validation.MinimumLengthValidator", "OPTIONS": {"min_length": 12}},
# Reject common passwords (e.g. "password", "123456") {"NAME": "buraq.contrib.auth.password_validation.CommonPasswordValidator"},
# Reject passwords that are entirely numeric {"NAME": "buraq.contrib.auth.password_validation.NumericPasswordValidator"},
# Reject passwords too similar to username / email {"NAME": "buraq.contrib.auth.password_validation.UserAttributeSimilarityValidator"},
# Guard against bcrypt DoS — reject very long passwords {"NAME": "buraq.contrib.auth.password_validation.MaximumLengthValidator", "OPTIONS": {"max_length": 4096}},]See Password Validation for usage details.
Sessions
Section titled “Sessions”SESSION_COOKIE_NAME = "buraq_session"SESSION_COOKIE_MAX_AGE = 1209600 # 2 weeks in secondsSESSION_COOKIE_HTTPONLY = TrueSESSION_COOKIE_SAMESITE = "lax"Templates and time
Section titled “Templates and time”Template context processors
Section titled “Template context processors”TEMPLATE_CONTEXT_PROCESSORS = [ "buraq.template.context_processors.request", # injects request "buraq.template.context_processors.auth", # injects user "buraq.template.context_processors.debug", # injects DEBUG flag "buraq.template.context_processors.i18n", # injects LANGUAGE_CODE "myapp.context_processors.site_settings", # custom processor]See Context Processors for writing custom processors.
Timezone
Section titled “Timezone”USE_TZ = True # store and return timezone-aware datetimes (default: True)TIME_ZONE = "UTC" # default timezone — any IANA name, e.g. "America/New_York"Working with settings
Section titled “Working with settings”Seeing every setting
Section titled “Seeing every setting”Buraq has far more settings than a project names — anything absent keeps its
default, which is why a scaffolded config/settings.py is short. To see the
full list with the values actually in force:
buraq diffsettings --all # every setting; ### marks the ones you changedburaq diffsettings # only what differs from the defaultsLoading settings yourself
Section titled “Loading settings yourself”The application and the CLI both find and apply your settings module on their own. A standalone script — a cron job, a data import, a migration run — runs in a process where nothing has, so it can do the same explicitly:
from buraq.conf import load_settings_module, settings
load_settings_module() # or load_settings_module("config.prod_settings")print(settings.DATABASE_URL)With no argument it uses BURAQ_SETTINGS_MODULE if set, then looks for
config/settings.py, ./settings.py, and finally a single top-level package
containing settings.py. discover_settings_module() performs that search
alone and returns the module name, or None when the layout is ambiguous.
Most scripts want buraq.apps.configure() instead, which
does this and imports your models.
Full defaults reference
Section titled “Full defaults reference”All settings have defaults. You only need to specify what you want to override.
See buraq/conf/defaults.py for the complete list.