Skip to main content

karni

Batteries-included Django glue: one call assembles the settings every Django + DRF + Celery project repeats, with production-safe defaults, startup validation, and an escape hatch for every single value. On top of the settings core it ships the three batteries every project rewrites:

  • karni.accounts — email-based swappable user, JWT or session auth endpoints, verified-email / password-reset / email-change flows, roles, optional TOTP 2FA and social login (docs)
  • karni.api — class EventViewSet(BaseViewSet): model = Event gives CRUD + filtering + search + expansion + OpenAPI, auto-routed (docs)
  • karni.admin — zero-config django-unfold admin: every model registered with derived columns, filters, search and soft-delete handling (docs)
pip install karni            # core
pip install 'karni[s3]'      # + S3-compatible storage (django-storages, boto3)
pip install 'karni[images]'  # + thumbnailing (Pillow)
pip install 'karni[sentry]'  # + Sentry (sentry-sdk)
pip install 'karni[social]'  # + social login (django-allauth)
pip install 'karni[2fa]'     # + TOTP two-factor auth (django-otp)

A whole settings.py

from karni.conf import karni_settings

karni_settings(globals())

# Project-specific settings below — anything defined here wins.
INSTALLED_APPS += [
    # "myapp",
]

That call configures: INSTALLED_APPS, middleware, Postgres from DATABASE_URL, Redis cache, DRF (pagination, filter backends, throttling, drf-spectacular schema), Celery (+ django-celery-beat, django-celery-results), file storage (local or S3-compatible), structlog logging (console in dev, JSON in prod), security headers, CORS, and optional Sentry. At startup the merged settings are validated by a Pydantic model and every bad value is reported at once (KARNI_VALIDATE = False skips this).

Overriding defaults

karni_settings() uses setdefault semantics — it never overwrites a name you already defined. Three layers, strongest first:

  1. Assign after the call — always wins: REST_FRAMEWORK["PAGE_SIZE"] = 20
  2. Define before the call — never touched. For INSTALLED_APPS and MIDDLEWARE, Karni appends its missing entries after yours instead of replacing the list.
  3. Keyword overrides — karni_settings(globals(), CELERY_TASK_TIME_LIMIT=60) replaces the Karni default (whole-value replacement) but still yields to names defined in the module.

Most defaults also read environment variables (via django-environ), so the same image runs in dev and prod with only a .env change.

Profiles

DJANGO_ENV=dev (default) or DJANGO_ENV=prod — or force one with karni_settings(globals(), env_name="prod").

dev prod
DEBUG True False
ALLOWED_HOSTS ["*"] required, from env
SECRET_KEY insecure default allowed required, validated
Logging colorized console (structlog) JSON lines (structlog)
CORS allow all origins CORS_ALLOWED_ORIGINS only
Security headers off HSTS, SSL redirect, secure cookies, nosniff, X-Frame-Options: DENY

Environment variables

Variable Default Meaning
DJANGO_ENV dev settings profile: dev or prod
SECRET_KEY insecure dev key required in prod (validation fails otherwise)
DEBUG dev True / prod False debug mode
ALLOWED_HOSTS dev * / prod empty comma-separated; required in prod
DATABASE_URL postgres://karni:karni@db:5432/karni database DSN
REDIS_URL redis://redis:6379/0 cache + Celery broker
CORS_ALLOWED_ORIGINS empty comma-separated origins
KARNI_PAGE_SIZE 50 DRF default page size
THROTTLE_ANON / THROTTLE_USER 100/min / 1000/min DRF throttle rates
PROJECT_NAME karni-project API title, Celery app name
KARNI_STORAGE local local or s3
AWS_ACCESS_KEY_ID, AWS_SECRET_ACCESS_KEY, AWS_STORAGE_BUCKET_NAME, AWS_S3_ENDPOINT_URL, AWS_S3_REGION_NAME empty S3-compatible storage (MinIO/R2 via endpoint URL)
SENTRY_DSN empty Sentry disabled when empty
SENTRY_TRACES_SAMPLE_RATE 0.0 Sentry tracing sample rate
MEDIA_ROOT / STATIC_ROOT /data/media / /data/static file roots

Celery

# config/celery.py
from karni.celery import create_celery_app

app = create_celery_app()

Broker, django-db results, database beat scheduler and task autodiscovery are configured from the CELERY_* settings that karni_settings() provided. Periodic tasks declared with karni.schedule.every() / cron() in <app>/schedules.py are merged into the beat schedule (docs/scheduling.md). Model lifecycle listeners live in <app>/listeners.py (docs/events.md). manage.py karni_routes and manage.py karni_schedules list every URL and every schedule (--json for agents).

Health checks

# config/urls.py
path("health/", include("karni.health.urls")),

/health/ is a no-I/O liveness probe; /health/ready/ runs the checks in KARNI_HEALTH_CHECKS (Postgres, Redis, Celery by default — a list of dotted paths you can extend or replace) and returns 200 or 503 with per-check detail.

Storage & thumbnails

KARNI_STORAGE=s3 switches the default storage to karni.storage.S3Storage (S3-compatible, endpoint-aware); anything else uses local FileSystemStorage. karni.storage.thumbnails.make_thumbnail() produces aspect-preserving thumbnails; swap the implementation via the KARNI_THUMBNAILER dotted-path setting.

Development

cd packages/karni
pip install -e . --group dev
pytest
ruff check .

Metadata

Release files for karni 0.3.1

For a detailed explanation of source distributions (sdists) and built distributions (wheels), please see the package formats documentation.

Source distribution (sdist)

Source distribution for karni 0.3.1
File Size Uploaded Provenance
karni-0.3.1.tar.gz 600.4 kB Without provenance Details

Built distribution (wheel)

Table of built distributions (wheels) for karni 0.3.1
File Interpreter ABI Platform
karni-0.3.1-py3-none-any.whl Python 3 none any Details

Total release size: 1.1 MB

Release files / karni-0.3.1.tar.gz

Download URL karni-0.3.1.tar.gz
Size 600.4 kB
Tags Source
SHA-256 checksum
How to use checksums
25ab527096a9ab264a0e854c338affe99704b4c3b8e9e0589252e4d61466ad05
BLAKE2b-256 checksum
How to use checksums
82980ed7baf14ae224c4268cb4cd283662097413ae30ea0beff4d0ce5b6b65fc
Upload date
Uploaded using Trusted Publishing?
What is trusted publishing?
No
Uploaded via twine/7.0.0 CPython/3.13.16

Release files / karni-0.3.1-py3-none-any.whl

Download URL karni-0.3.1-py3-none-any.whl
Size 491.1 kB
Tags Python 3
SHA-256 checksum
How to use checksums
9b2cc28611217c91c6faffa512866590a6a6e6cb72ee8cbe51a528891134671c
BLAKE2b-256 checksum
How to use checksums
baace192092e94caf9268310f37b1742b09e7aa6630851de741d9e5f851695ac
Upload date
Uploaded using Trusted Publishing?
What is trusted publishing?
No
Uploaded via twine/7.0.0 CPython/3.13.16

Security for karni 0.3.1

Provenance

Provenance describes where a file came from. On PyPI, provenance is shared via attestations, which provide a verifiable record of the build or publishing details. View details, limitations and caveats.

No provenance found

None of the files in this release were uploaded with provenance metadata.

A note on package security

PyPI is a repository for distributing packages, not a service for auditing them. While third-party security researchers and our staff do their best to detect and remove malicious packages, PyPI cannot guarantee the quality, security or suitability of any given package.

Release history Release notifications | RSS feed

This release

0.3.1 This release

2 release files No provenance

Anthropic, PBC Visionary sponsor Bloomberg Visionary sponsor Hudson River Trading Visionary sponsor Meta Visionary sponsor NVIDIA Visionary sponsor Microsoft Sustainability sponsor Depot Continuous Integration AWS Cloud computing and Security Sponsor Datadog Monitoring Fastly CDN Google Download Analytics Sentry Error logging StatusPage Status page