Files
mnemosyne/docs/Red Panda Standards_Django_V1-00.md
Robert Helewka 99bdb4ac92 Add Themis application with custom widgets, views, and utilities
- Implemented custom form widgets for date, time, and datetime fields with DaisyUI styling.
- Created utility functions for formatting dates, times, and numbers according to user preferences.
- Developed views for profile settings, API key management, and notifications, including health check endpoints.
- Added URL configurations for Themis tests and main application routes.
- Established test cases for custom widgets to ensure proper functionality and integration.
- Defined project metadata and dependencies in pyproject.toml for package management.
2026-03-21 02:00:18 +00:00

10 KiB

🐾 Red Panda Approval™

This project follows Red Panda Approval standards — our gold standard for Django application quality. Code must be elegant, reliable, and maintainable to earn the approval of our adorable red panda judges.

The 5 Sacred Django Criteria

  1. Fresh Migration Test — Clean migrations from empty database
  2. Elegant Simplicity — No unnecessary complexity
  3. Observable & Debuggable — Proper logging and error handling
  4. Consistent Patterns — Follow Django conventions
  5. Actually Works — Passes all checks and serves real user needs

Environment Standards

  • Virtual environment: ~/env/PROJECT/bin/activate
  • Use pyproject.toml for project configuration (no setup.py, no requirements.txt)
  • Python version: specified in pyproject.toml
  • Dependencies: floor-pinned with ceiling (e.g. Django>=5.2,<6.0)

Dependency Pinning

# Correct — floor pin with ceiling
dependencies = [
    "Django>=5.2,<6.0",
    "djangorestframework>=3.14,<4.0",
    "cryptography>=41.0,<45.0",
]

# Wrong — exact pins in library packages
dependencies = [
    "Django==5.2.7",  # too strict, breaks downstream
]

Exact pins (==) are only appropriate in application-level lock files, not in reusable library packages.

Directory Structure

myproject/ # Git repository root ├── .gitignore ├── README.md ├── pyproject.toml # Project configuration (moved to repo root) ├── docker-compose.yml ├── .env # Docker Compose environment (DATABASE_URL=postgres://...) ├── .env.example │ ├── project/ # Django project root (manage.py lives here) │ ├── manage.py │ ├── Dockerfile │ ├── .env # Local development environment (DATABASE_URL=sqlite:///...) │ ├── .env.example │ │ │ ├── config/ # Django configuration module │ │ ├── init.py │ │ ├── settings.py │ │ ├── urls.py │ │ ├── wsgi.py │ │ └── asgi.py │ │ │ ├── accounts/ # Django app │ │ ├── init.py │ │ ├── models.py │ │ ├── views.py │ │ └── urls.py │ │ │ ├── blog/ # Django app │ │ ├── init.py │ │ ├── models.py │ │ ├── views.py │ │ └── urls.py │ │ │ ├── static/ │ │ ├── css/ │ │ └── js/ │ │ │ └── templates/ │ └── base.html │ ├── web/ # Nginx configuration │ └── nginx.conf │ ├── db/ # PostgreSQL configuration │ └── postgresql.conf │ └── docs/ # Project documentation └── index.md

Settings Structure

  • Use a single settings.py file
  • Use django-environ or python-dotenv for environment variables
  • Never commit .env files to version control
  • Provide .env.example with all required variables documented
  • Create .gitignore file
  • Create a .dockerignore file

Code Organization

  • Imports: PEP 8 ordering (stdlib, third-party, local)
  • Type hints on function parameters
  • CSS: External .css files only (no inline styles, no embedded <style> tags)
  • JS: External .js files only (no inline handlers, no embedded <script> blocks)
  • Maximum file length: 1000 lines
  • If a file exceeds 500 lines, consider splitting by domain concept

Database Conventions

  • Migrations run cleanly from empty database
  • Never edit deployed migrations
  • Use meaningful migration names: --name add_email_to_profile
  • One logical change per migration when possible
  • Test migrations both forward and backward

Development vs Production

  • Development: SQLite
  • Production: PostgreSQL

Caching

  • Expensive queries are cached
  • Cache keys follow naming convention
  • TTLs are appropriate (not infinite)
  • Invalidation is documented
  • Key Naming Pattern: {app}:{model}:{identifier}:{field}

Model Naming

  • Model names: singular PascalCase (User, BlogPost, OrderItem)
  • Correct English pluralization on related names
  • All models have created_at and updated_at
  • All models define str and get_absolute_url
  • TextChoices used for status fields
  • related_name defined on ForeignKey fields
  • Related names: plural snake_case with proper English pluralization

Forms

  • Use ModelForm with explicit fields list (never all)

Field Naming

  • Foreign keys: singular without _id suffix (author, category, parent)
  • Boolean fields: use prefixes (is_active, has_permission, can_edit)
  • Date fields: use suffixes (created_at, updated_at, published_on)
  • Avoid abbreviations (use description, not desc)

Required Model Fields

  • All models should include:
    • created_at = models.DateTimeField(auto_now_add=True)
    • updated_at = models.DateTimeField(auto_now=True)
  • Consider adding:
    • id = models.UUIDField(primary_key=True) for public-facing models
    • is_active = models.BooleanField(default=True) for soft deletes

Indexing

  • Add db_index=True to frequently queried fields
  • Use Meta.indexes for composite indexes
  • Document why each index exists

Queries

  • Use select_related() for foreign keys
  • Use prefetch_related() for reverse relations and M2M
  • Avoid queries in loops (N+1 problem)
  • Use .only() and .defer() for large models
  • Add comments explaining complex querysets

Docstrings

  • Use Sphinx style docstrings
  • Document all public functions, classes, and modules
  • Skip docstrings for obvious one-liners and standard Django overrides

Views

  • Use Function-Based Views (FBVs) exclusively
  • Explicit logic is preferred over implicit inheritance
  • Extract shared logic into utility functions

URLs & Identifiers

  • Public URLs use short UUIDs (12 characters) via shortuuid
  • Never expose sequential IDs in URLs (security/enumeration risk)
  • Internal references may use standard UUIDs or PKs

URL Patterns

  • Resource-based URLs (RESTful style)
  • Namespaced URL names per app
  • Trailing slashes (Django default)
  • Flat structure preferred over deep nesting

Background Tasks

  • All tasks are run synchronously unless the design specifies background tasks are needed for long operations
  • Long operations use Celery tasks
  • Use Memcached, task progress pattern: {app}:task:{task_id}:progress
  • Tasks are idempotent
  • Tasks include retry logic
  • Tasks live in app/tasks.py
  • RabbitMQ is the Message Broker
  • Flower Monitoring: Use for debugging failed tasks

Testing

  • Framework: Django TestCase (not pytest)
  • Separate test files per module: test_models.py, test_views.py, test_forms.py

Frontend Standards

New Projects (DaisyUI + Tailwind)

  • DaisyUI 4 via CDN for component classes
  • Tailwind CSS via CDN for utility classes
  • Theme management via Themis (DaisyUI data-theme attribute)
  • All apps extend themis/base.html for consistent navigation
  • No inline styles or scripts

Existing Projects (Bootstrap 5)

  • Bootstrap 5 via CDN
  • Bootstrap Icons via CDN
  • Bootswatch for theme variants (if applicable)
  • django-bootstrap5 and crispy-bootstrap5 for form rendering

Preferred Packages

Core Django

  • django>=5.2,<6.0
  • django-environ — Environment variables

Authentication & Security

  • django-allauth — User management
  • django-allauth-2fa — Two-factor authentication

API Development

  • djangorestframework>=3.14,<4.0 — REST APIs
  • drf-spectacular — OpenAPI/Swagger documentation

Encryption

  • cryptography — Fernet encryption for secrets/API keys

Background Tasks

  • celery — Async task queue
  • django-celery-progress — Progress bars
  • flower — Celery monitoring

Caching

  • pymemcache — Memcached backend

Database

  • dj-database-url — Database URL configuration
  • psycopg[binary] — PostgreSQL adapter
  • shortuuid — Short UUIDs for public URLs

Production

  • gunicorn — WSGI server

Shared Apps

  • django-heluca-themis — User preferences, themes, key management, navigation

Deprecated / Removed

  • pytz — Use stdlib zoneinfo (Python 3.9+, Django 4+)
  • Pillow — Only add if your app needs ImageField
  • django-heluca-core — Replaced by Themis

Anti-Patterns to Avoid

Models

  • Don't use Model.objects.get() without handling DoesNotExist
  • Don't use null=True on CharField or TextField (use blank=True, default="")
  • Don't use related_name='+' unless you have a specific reason
  • Don't override save() for business logic (use signals or service functions)
  • Don't use auto_now=True on fields you might need to manually set
  • Don't use ForeignKey without specifying on_delete explicitly
  • Don't use Meta.ordering on large tables (specify ordering in queries)

Queries

  • Don't query inside loops (N+1 problem)
  • Don't use .all() when you need a subset
  • Don't use raw SQL unless absolutely necessary
  • Don't forget select_related() and prefetch_related()

Views

  • Don't put business logic in views
  • Don't use request.POST.get() without validation (use forms)
  • Don't return sensitive data in error messages
  • Don't forget login_required decorator on protected views

Forms

  • Don't use fields = '__all__' in ModelForm
  • Don't trust client-side validation alone
  • Don't use exclude in ModelForm (use explicit fields)

Templates

  • Don't use {{ variable }} for URLs (use {% url %} tag)
  • Don't put logic in templates
  • Don't use inline CSS or JavaScript (external files only)
  • Don't forget {% csrf_token %} in forms

Security

  • Don't store secrets in settings.py (use environment variables)
  • Don't commit .env files to version control
  • Don't use DEBUG=True in production
  • Don't expose sequential IDs in public URLs
  • Don't use mark_safe() on user-supplied content
  • Don't disable CSRF protection

Imports & Code Style

  • Don't use from module import *
  • Don't use mutable default arguments
  • Don't use bare except: clauses
  • Don't ignore linter warnings without documented reason

Migrations

  • Don't edit migrations that have been deployed
  • Don't use RunPython without a reverse function
  • Don't add non-nullable fields without a default value

Celery Tasks

  • Don't pass model instances to tasks (pass IDs and re-fetch)
  • Don't assume tasks run immediately
  • Don't forget retry logic for external service calls