{"id":"6b6a1ee8-9b0d-41da-a21e-3a6022df00bd","entityType":"agent","slug":"clawhub-skills-1kalin-afrexai-django-production","name":"afrexai-django-production","canonicalUrl":"https://www.xpersona.co/agent/clawhub-skills-1kalin-afrexai-django-production","canonicalPath":"/agent/clawhub-skills-1kalin-afrexai-django-production","generatedAt":"2026-10-10T04:24:15.923Z","source":"CLAWHUB","claimStatus":"UNCLAIMED","verificationTier":"NONE","summary":{"evidence":{"source":"editorial-content","verified":true,"confidence":"high","updatedAt":"2026-04-15T00:45:39.800Z","emptyReason":null},"description":"Django Production Engineering Django Production Engineering Complete methodology for building, scaling, and operating production Django applications. From project structure to deployment, security to performance — every decision framework a Django team needs. Quick Health Check Run this 8-signal triage on any Django project: | # | Signal | Check | Healthy | |---|--------|-------|---------| | 1 | Settings split | settings/base.py, local.py, produc","descriptionLabel":"Technical summary","evidenceSummary":"Capability contract not published. No trust telemetry is available yet. Last updated 4/15/2026.","installCommand":"clawhub skill install skills:1kalin:afrexai-django-production","sourceUrl":"https://github.com/openclaw/skills/tree/main/skills/1kalin/afrexai-django-production","homepage":null,"primaryLinks":[{"label":"View on ClawHub","url":"https://github.com/openclaw/skills/tree/main/skills/1kalin/afrexai-django-production","kind":"source"}],"safetyScore":84,"overallRank":62,"popularityScore":50,"trustScore":null,"claimedByName":null,"isOwner":false,"seoDescription":"Django Production Engineering Django Production Engineering Complete methodology for building, scaling, and operating production Django applications. From proje"},"coverage":{"evidence":{"source":"public-profile","verified":false,"confidence":"medium","updatedAt":"2026-04-15T00:45:39.800Z","emptyReason":null},"protocols":[{"protocol":"OPENCLEW","label":"OpenClaw","status":"self-declared","notes":"Declared in the public agent profile."}],"capabilities":[{"label":"access","status":"self-declared"},{"label":"produce","status":"self-declared"}],"verifiedCount":0,"selfDeclaredCount":3,"capabilityMatrix":{"rows":[{"key":"OPENCLEW","type":"protocol","support":"unknown","confidenceSource":"profile","notes":"Listed on profile"},{"key":"access","type":"capability","support":"supported","confidenceSource":"profile","notes":"Declared in agent profile metadata"},{"key":"produce","type":"capability","support":"supported","confidenceSource":"profile","notes":"Declared in agent profile metadata"}],"flattenedTokens":"protocol:OPENCLEW|unknown|profile capability:access|supported|profile capability:produce|supported|profile"}},"adoption":{"evidence":{"source":"no-adoption-signals","verified":false,"confidence":"low","updatedAt":"2026-04-15T00:45:39.800Z","emptyReason":"No source adoption metrics were available."},"stars":null,"forks":null,"downloads":null,"packageName":null,"latestVersion":null,"tractionLabel":null},"release":{"evidence":{"source":"agent-index","verified":false,"confidence":"medium","updatedAt":"2026-02-25T06:17:19.264Z","emptyReason":null},"lastUpdatedAt":"2026-04-15T00:45:39.800Z","lastCrawledAt":"2026-02-25T06:17:19.264Z","lastIndexedAt":null,"nextCrawlAt":"2026-02-26T06:17:19.264Z","lastVerifiedAt":null,"highlights":[]},"execution":{"evidence":{"source":"CLAWHUB","verified":false,"confidence":"low","updatedAt":null,"emptyReason":"No published capability contract is available yet."},"installCommand":"clawhub skill install skills:1kalin:afrexai-django-production","setupComplexity":"low","setupSteps":["Setup complexity is LOW. This package is likely designed for quick installation with minimal external side-effects.","Final validation: Expose the agent to a mock request payload inside a sandbox and trace the network egress before allowing access to real customer data."],"contract":{"contractStatus":"missing","authModes":[],"requires":[],"forbidden":[],"supportsMcp":false,"supportsA2a":false,"supportsStreaming":false,"inputSchemaRef":null,"outputSchemaRef":null,"dataRegion":null,"contractUpdatedAt":null,"sourceUpdatedAt":null,"freshnessSeconds":null},"invocationGuide":{"preferredApi":{"snapshotUrl":"https://www.xpersona.co/api/v1/agents/clawhub-skills-1kalin-afrexai-django-production/snapshot","contractUrl":"https://www.xpersona.co/api/v1/agents/clawhub-skills-1kalin-afrexai-django-production/contract","trustUrl":"https://www.xpersona.co/api/v1/agents/clawhub-skills-1kalin-afrexai-django-production/trust"},"curlExamples":["curl -s \"https://www.xpersona.co/api/v1/agents/clawhub-skills-1kalin-afrexai-django-production/snapshot\"","curl -s \"https://www.xpersona.co/api/v1/agents/clawhub-skills-1kalin-afrexai-django-production/contract\"","curl -s \"https://www.xpersona.co/api/v1/agents/clawhub-skills-1kalin-afrexai-django-production/trust\""],"jsonRequestTemplate":{"query":"summarize this repo","constraints":{"maxLatencyMs":2000,"protocolPreference":["OPENCLEW"]}},"jsonResponseTemplate":{"ok":true,"result":{"summary":"...","confidence":0.9},"meta":{"source":"CLAWHUB","generatedAt":"2026-10-10T04:24:15.923Z"}},"retryPolicy":{"maxAttempts":3,"backoffMs":[500,1500,3500],"retryableConditions":["HTTP_429","HTTP_503","NETWORK_TIMEOUT"]}},"endpoints":{"dossierUrl":"https://www.xpersona.co/api/v1/agents/clawhub-skills-1kalin-afrexai-django-production/dossier","snapshotUrl":"https://www.xpersona.co/api/v1/agents/clawhub-skills-1kalin-afrexai-django-production/snapshot","contractUrl":"https://www.xpersona.co/api/v1/agents/clawhub-skills-1kalin-afrexai-django-production/contract","trustUrl":"https://www.xpersona.co/api/v1/agents/clawhub-skills-1kalin-afrexai-django-production/trust"}},"reliability":{"evidence":{"source":"runtime-metrics","verified":false,"confidence":"low","updatedAt":null,"emptyReason":"No trust, reliability, or runtime telemetry is available."},"trust":{"status":"unavailable","handshakeStatus":"UNKNOWN","verificationFreshnessHours":null,"reputationScore":null,"p95LatencyMs":null,"successRate30d":null,"fallbackRate":null,"attempts30d":null,"trustUpdatedAt":null,"trustConfidence":"unknown","sourceUpdatedAt":null,"freshnessSeconds":null},"decisionGuardrails":{"doNotUseIf":["Contract metadata is missing or unavailable for deterministic execution."],"safeUseWhen":[],"riskFlags":["missing_or_unavailable_contract","trust_data_unavailable","schema_references_missing"],"operationalConfidence":"low"},"executionMetrics":{"observedLatencyMsP50":null,"observedLatencyMsP95":null,"estimatedCostUsd":null,"uptime30d":null,"rateLimitRpm":null,"rateLimitBurst":null,"lastVerifiedAt":null,"verificationSource":null},"runtimeMetrics":{"successRate":null,"avgLatencyMs":null,"avgCostUsd":null,"hallucinationRate":null,"retryRate":null,"disputeRate":null,"p50Latency":null,"p95Latency":null,"lastUpdated":null}},"benchmarks":{"evidence":{"source":"no-benchmark-data","verified":false,"confidence":"low","updatedAt":null,"emptyReason":"No benchmark suites or observed failure patterns are available."},"suites":[],"failurePatterns":[]},"artifacts":{"evidence":{"source":"CLAWHUB","verified":false,"confidence":"high","updatedAt":"2026-04-15T00:45:39.800Z","emptyReason":null},"readme":"# Django Production Engineering\n\nComplete methodology for building, scaling, and operating production Django applications. From project structure to deployment, security to performance — every decision framework a Django team needs.\n\n## Quick Health Check\n\nRun this 8-signal triage on any Django project:\n\n| # | Signal | Check | Healthy |\n|---|--------|-------|---------|\n| 1 | Settings split | `settings/base.py`, `local.py`, `production.py` exist | ✅ Split by env |\n| 2 | Secret management | `SECRET_KEY` not in code, `DEBUG=False` in prod | ✅ Env vars / vault |\n| 3 | Database | Using connection pooling (pgbouncer / django-db-conn-pool) | ✅ Pool configured |\n| 4 | Migrations | `python manage.py showmigrations` — no unapplied | ✅ All applied |\n| 5 | Static files | `collectstatic` + CDN/whitenoise configured | ✅ Served properly |\n| 6 | Async tasks | Celery/django-q/Huey for background work | ✅ Not blocking views |\n| 7 | Caching | Cache backend configured (Redis/Memcached) | ✅ Not DummyCache |\n| 8 | Security | `python manage.py check --deploy` passes | ✅ All checks pass |\n\n**Score: count ✅ / 8** — Below 6 = stop and fix foundations first.\n\n---\n\n## Phase 1: Project Architecture\n\n### Recommended Structure\n\n```\nmyproject/\n├── config/                    # Project config (was myproject/)\n│   ├── __init__.py\n│   ├── settings/\n│   │   ├── __init__.py\n│   │   ├── base.py           # Shared settings\n│   │   ├── local.py          # Development\n│   │   ├── staging.py        # Staging\n│   │   └── production.py     # Production\n│   ├── urls.py               # Root URL conf\n│   ├── wsgi.py\n│   ├── asgi.py\n│   └── celery.py             # Celery app\n├── apps/\n│   ├── users/                # Custom user model (ALWAYS)\n│   │   ├── models.py\n│   │   ├── managers.py\n│   │   ├── admin.py\n│   │   ├── serializers.py\n│   │   ├── views.py\n│   │   ├── urls.py\n│   │   ├── services.py       # Business logic\n│   │   ├── selectors.py      # Complex queries\n│   │   ├── tests/\n│   │   │   ├── test_models.py\n│   │   │   ├── test_views.py\n│   │   │   └── test_services.py\n│   │   └── migrations/\n│   ├── core/                 # Shared utilities\n│   │   ├── models.py         # Abstract base models\n│   │   ├── permissions.py\n│   │   ├── pagination.py\n│   │   ├── exceptions.py\n│   │   └── middleware.py\n│   └── <domain>/             # Feature apps\n├── templates/\n├── static/\n├── media/\n├── requirements/\n│   ├── base.txt\n│   ├── local.txt\n│   └── production.txt\n├── docker/\n├── scripts/\n├── manage.py\n├── pyproject.toml\n├── Makefile\n└── .env.example\n```\n\n### 7 Architecture Rules\n\n1. **Custom user model from Day 1** — `AUTH_USER_MODEL = 'users.User'`. Changing later is extremely painful.\n2. **Fat services, thin views** — Views handle HTTP; `services.py` handles business logic; `selectors.py` handles complex queries.\n3. **One app per domain** — Not per model. Group related models in one app.\n4. **Settings split by environment** — Never use `if DEBUG` conditionally in a single file.\n5. **Abstract base models in core** — `TimeStampedModel`, `UUIDModel` shared across apps.\n6. **Separate requirements files** — `base.txt` (shared), `local.txt` (dev tools), `production.txt` (gunicorn, sentry).\n7. **Keep apps decoupled** — Apps communicate through services, not by importing each other's models directly. Use signals sparingly.\n\n### Abstract Base Models\n\n```python\n# apps/core/models.py\nimport uuid\nfrom django.db import models\n\nclass TimeStampedModel(models.Model):\n    created_at = models.DateTimeField(auto_now_add=True, db_index=True)\n    updated_at = models.DateTimeField(auto_now=True)\n\n    class Meta:\n        abstract = True\n\nclass UUIDModel(models.Model):\n    id = models.UUIDField(primary_key=True, default=uuid.uuid4, editable=False)\n\n    class Meta:\n        abstract = True\n\nclass SoftDeleteModel(models.Model):\n    is_deleted = models.BooleanField(default=False, db_index=True)\n    deleted_at = models.DateTimeField(null=True, blank=True)\n\n    class Meta:\n        abstract = True\n\n    def soft_delete(self):\n        from django.utils import timezone\n        self.is_deleted = True\n        self.deleted_at = timezone.now()\n        self.save(update_fields=[\"is_deleted\", \"deleted_at\"])\n```\n\n---\n\n## Phase 2: ORM Mastery & Query Optimization\n\n### N+1 Query Prevention\n\n```python\n# ❌ N+1 — fires 1 + N queries\nfor order in Order.objects.all():\n    print(order.customer.name)        # Each access = new query\n    for item in order.items.all():    # Each access = new query\n        print(item.product.name)      # Each access = new query\n\n# ✅ Optimized — fires 3 queries total\norders = (\n    Order.objects\n    .select_related(\"customer\")              # FK/OneToOne — JOIN\n    .prefetch_related(\n        Prefetch(\n            \"items\",\n            queryset=OrderItem.objects\n                .select_related(\"product\")   # Nested FK\n                .only(\"id\", \"quantity\", \"product__name\")  # Only needed fields\n        )\n    )\n)\n```\n\n### select_related vs prefetch_related Decision\n\n| Relationship | Use | Why |\n|---|---|---|\n| ForeignKey (forward) | `select_related` | SQL JOIN, single query |\n| OneToOneField | `select_related` | SQL JOIN, single query |\n| ManyToMany | `prefetch_related` | Separate query, Python join |\n| Reverse FK (set) | `prefetch_related` | Separate query, Python join |\n| Filtered prefetch | `Prefetch()` object | Custom queryset |\n\n### QuerySet Evaluation Rules\n\n```python\n# QuerySets are LAZY — no database hit until evaluated\nqs = Order.objects.filter(status=\"pending\")  # No query yet\n\n# These EVALUATE the queryset (trigger SQL):\nlist(qs)           # Iteration\nlen(qs)            # Use qs.count() instead\nbool(qs)           # Use qs.exists() instead\nqs[0]              # Indexing\nrepr(qs)           # In shell/debugger\nfor obj in qs:     # Iteration\nif qs:             # Use qs.exists()\n```\n\n### Bulk Operations\n\n```python\n# ❌ N queries\nfor item in items:\n    Product.objects.create(name=item[\"name\"], price=item[\"price\"])\n\n# ✅ 1 query\nProduct.objects.bulk_create(\n    [Product(name=i[\"name\"], price=i[\"price\"]) for i in items],\n    batch_size=1000,\n    ignore_conflicts=True,  # Skip duplicates\n)\n\n# ✅ Bulk update\nProduct.objects.filter(category=\"sale\").update(\n    price=F(\"price\") * 0.9  # 10% discount — single query, no race conditions\n)\n\n# ✅ Bulk update with different values\nproducts = Product.objects.filter(id__in=ids)\nfor p in products:\n    p.price = new_prices[p.id]\nProduct.objects.bulk_update(products, [\"price\"], batch_size=1000)\n```\n\n### Database Functions & Expressions\n\n```python\nfrom django.db.models import F, Q, Value, Count, Avg, Sum, Case, When\nfrom django.db.models.functions import Coalesce, Lower, TruncMonth\n\n# Conditional aggregation\nOrder.objects.aggregate(\n    total_revenue=Sum(\"amount\"),\n    paid_revenue=Sum(\"amount\", filter=Q(status=\"paid\")),\n    refund_count=Count(\"id\", filter=Q(status=\"refunded\")),\n    avg_order_value=Avg(\"amount\", filter=Q(status=\"paid\")),\n)\n\n# Annotate with computed fields\ncustomers = (\n    Customer.objects\n    .annotate(\n        order_count=Count(\"orders\"),\n        total_spent=Coalesce(Sum(\"orders__amount\"), Value(0)),\n        last_order=Max(\"orders__created_at\"),\n    )\n    .filter(order_count__gte=5)\n    .order_by(\"-total_spent\")\n)\n\n# Monthly revenue report\nmonthly = (\n    Order.objects\n    .filter(status=\"paid\")\n    .annotate(month=TruncMonth(\"created_at\"))\n    .values(\"month\")\n    .annotate(\n        revenue=Sum(\"amount\"),\n        count=Count(\"id\"),\n        avg=Avg(\"amount\"),\n    )\n    .order_by(\"month\")\n)\n\n# Case/When for computed status\nusers = User.objects.annotate(\n    tier=Case(\n        When(total_spent__gte=10000, then=Value(\"platinum\")),\n        When(total_spent__gte=5000, then=Value(\"gold\")),\n        When(total_spent__gte=1000, then=Value(\"silver\")),\n        default=Value(\"bronze\"),\n    )\n)\n```\n\n### Index Strategy\n\n```python\nclass Order(TimeStampedModel):\n    customer = models.ForeignKey(Customer, on_delete=models.CASCADE)\n    status = models.CharField(max_length=20, db_index=True)  # Single column\n    amount = models.DecimalField(max_digits=10, decimal_places=2)\n    \n    class Meta:\n        indexes = [\n            # Composite index — for queries filtering both\n            models.Index(fields=[\"status\", \"created_at\"], name=\"idx_order_status_created\"),\n            # Partial index — only index what you query\n            models.Index(\n                fields=[\"customer\"],\n                condition=Q(status=\"pending\"),\n                name=\"idx_order_pending_customer\",\n            ),\n            # Covering index (Postgres) — avoid table lookup\n            models.Index(\n                fields=[\"status\"],\n                include=[\"amount\", \"created_at\"],\n                name=\"idx_order_status_covering\",\n            ),\n        ]\n        # Default ordering impacts ALL queries — be intentional\n        ordering = [\"-created_at\"]\n```\n\n### 8 ORM Rules\n\n1. **Always use `select_related`/`prefetch_related`** — install django-debug-toolbar and watch query count.\n2. **Never use `.count()` + `.all()` together** — use `.exists()` for boolean checks.\n3. **Use `F()` expressions** for atomic updates — avoids race conditions.\n4. **Use `.only()` / `.defer()`** for large text/JSON fields you don't need.\n5. **Use `.values()` / `.values_list()`** when you don't need model instances.\n6. **Use `iterator(chunk_size=2000)`** for large result sets — reduces memory.\n7. **Profile with `django-silk` or `django-debug-toolbar`** — never guess at performance.\n8. **Use `Exists()` subqueries** instead of `__in` with large lists.\n\n---\n\n## Phase 3: Django REST Framework (DRF)\n\n### Serializer Patterns\n\n```python\n# apps/orders/serializers.py\nfrom rest_framework import serializers\n\nclass OrderListSerializer(serializers.ModelSerializer):\n    \"\"\"Lightweight for list views — minimal fields.\"\"\"\n    customer_name = serializers.CharField(source=\"customer.name\", read_only=True)\n    \n    class Meta:\n        model = Order\n        fields = [\"id\", \"customer_name\", \"status\", \"amount\", \"created_at\"]\n        read_only_fields = [\"id\", \"created_at\"]\n\nclass OrderDetailSerializer(serializers.ModelSerializer):\n    \"\"\"Full detail with nested items.\"\"\"\n    items = OrderItemSerializer(many=True, read_only=True)\n    customer = CustomerSerializer(read_only=True)\n    \n    class Meta:\n        model = Order\n        fields = \"__all__\"\n\nclass OrderCreateSerializer(serializers.Serializer):\n    \"\"\"Explicit create — don't use ModelSerializer for writes.\"\"\"\n    customer_id = serializers.UUIDField()\n    items = OrderItemInputSerializer(many=True)\n    notes = serializers.CharField(required=False, allow_blank=True)\n    \n    def validate_items(self, value):\n        if not value:\n            raise serializers.ValidationError(\"At least one item required.\")\n        return value\n    \n    def create(self, validated_data):\n        # Delegate to service layer\n        from apps.orders.services import create_order\n        return create_order(**validated_data)\n```\n\n### Service Layer Pattern\n\n```python\n# apps/orders/services.py\nfrom django.db import transaction\nfrom django.core.exceptions import ValidationError\n\ndef create_order(*, customer_id: str, items: list[dict], notes: str = \"\") -> Order:\n    \"\"\"\n    Create order with items atomically.\n    \n    Raises:\n        ValidationError: If customer not found or insufficient stock.\n    \"\"\"\n    customer = Customer.objects.filter(id=customer_id).first()\n    if not customer:\n        raise ValidationError(\"Customer not found.\")\n    \n    with transaction.atomic():\n        order = Order.objects.create(customer=customer, notes=notes)\n        \n        order_items = []\n        for item_data in items:\n            product = Product.objects.select_for_update().get(id=item_data[\"product_id\"])\n            if product.stock < item_data[\"quantity\"]:\n                raise ValidationError(f\"Insufficient stock for {product.name}\")\n            \n            product.stock -= item_data[\"quantity\"]\n            product.save(update_fields=[\"stock\"])\n            \n            order_items.append(\n                OrderItem(order=order, product=product, quantity=item_data[\"quantity\"], unit_price=product.price)\n            )\n        \n        OrderItem.objects.bulk_create(order_items)\n        order.amount = sum(i.unit_price * i.quantity for i in order_items)\n        order.save(update_fields=[\"amount\"])\n    \n    # Side effects OUTSIDE transaction\n    send_order_confirmation.delay(order.id)\n    return order\n```\n\n### ViewSet Best Practices\n\n```python\n# apps/orders/views.py\nfrom rest_framework import viewsets, status\nfrom rest_framework.decorators import action\nfrom rest_framework.response import Response\n\nclass OrderViewSet(viewsets.ModelViewSet):\n    permission_classes = [IsAuthenticated]\n    \n    def get_queryset(self):\n        \"\"\"Always scope to current user. Never return all objects.\"\"\"\n        return (\n            Order.objects\n            .filter(customer__user=self.request.user)\n            .select_related(\"customer\")\n            .prefetch_related(\"items__product\")\n        )\n    \n    def get_serializer_class(self):\n        \"\"\"Different serializers for different actions.\"\"\"\n        if self.action == \"list\":\n            return OrderListSerializer\n        if self.action in (\"create\",):\n            return OrderCreateSerializer\n        return OrderDetailSerializer\n    \n    def perform_create(self, serializer):\n        serializer.save()\n    \n    @action(detail=True, methods=[\"post\"])\n    def cancel(self, request, pk=None):\n        order = self.get_object()\n        from apps.orders.services import cancel_order\n        try:\n            cancel_order(order=order, cancelled_by=request.user)\n        except ValidationError as e:\n            return Response({\"error\": str(e)}, status=status.HTTP_400_BAD_REQUEST)\n        return Response({\"status\": \"cancelled\"})\n    \n    @action(detail=False, methods=[\"get\"])\n    def summary(self, request):\n        from apps.orders.selectors import get_order_summary\n        data = get_order_summary(user=request.user)\n        return Response(data)\n```\n\n### Pagination\n\n```python\n# apps/core/pagination.py\nfrom rest_framework.pagination import CursorPagination\n\nclass StandardCursorPagination(CursorPagination):\n    \"\"\"Cursor pagination — O(1) performance regardless of offset.\"\"\"\n    page_size = 25\n    page_size_query_param = \"page_size\"\n    max_page_size = 100\n    ordering = \"-created_at\"\n\n# settings/base.py\nREST_FRAMEWORK = {\n    \"DEFAULT_PAGINATION_CLASS\": \"apps.core.pagination.StandardCursorPagination\",\n    \"DEFAULT_THROTTLE_CLASSES\": [\n        \"rest_framework.throttling.AnonRateThrottle\",\n        \"rest_framework.throttling.UserRateThrottle\",\n    ],\n    \"DEFAULT_THROTTLE_RATES\": {\"anon\": \"100/hour\", \"user\": \"1000/hour\"},\n    \"DEFAULT_RENDERER_CLASSES\": [\"rest_framework.renderers.JSONRenderer\"],\n    \"DEFAULT_AUTHENTICATION_CLASSES\": [\n        \"rest_framework_simplejwt.authentication.JWTAuthentication\",\n    ],\n    \"EXCEPTION_HANDLER\": \"apps.core.exceptions.custom_exception_handler\",\n}\n```\n\n---\n\n## Phase 4: Authentication & Security\n\n### JWT Authentication (SimpleJWT)\n\n```python\n# config/settings/base.py\nfrom datetime import timedelta\n\nSIMPLE_JWT = {\n    \"ACCESS_TOKEN_LIFETIME\": timedelta(minutes=15),\n    \"REFRESH_TOKEN_LIFETIME\": timedelta(days=7),\n    \"ROTATE_REFRESH_TOKENS\": True,\n    \"BLACKLIST_AFTER_ROTATION\": True,\n    \"ALGORITHM\": \"HS256\",\n    \"AUTH_HEADER_TYPES\": (\"Bearer\",),\n}\n\n# Custom user model\n# apps/users/models.py\nfrom django.contrib.auth.models import AbstractUser\nfrom apps.users.managers import UserManager\n\nclass User(AbstractUser):\n    username = None  # Remove username field\n    email = models.EmailField(unique=True)\n    \n    USERNAME_FIELD = \"email\"\n    REQUIRED_FIELDS = []\n    \n    objects = UserManager()\n```\n\n### Security Settings (Production)\n\n```python\n# config/settings/production.py\nimport os\n\nSECRET_KEY = os.environ[\"DJANGO_SECRET_KEY\"]\nDEBUG = False\nALLOWED_HOSTS = os.environ[\"ALLOWED_HOSTS\"].split(\",\")\n\n# HTTPS\nSECURE_SSL_REDIRECT = True\nSECURE_HSTS_SECONDS = 31536000\nSECURE_HSTS_INCLUDE_SUBDOMAINS = True\nSECURE_HSTS_PRELOAD = True\nSESSION_COOKIE_SECURE = True\nCSRF_COOKIE_SECURE = True\nSECURE_PROXY_SSL_HEADER = (\"HTTP_X_FORWARDED_PROTO\", \"https\")\n\n# Content security\nSECURE_CONTENT_TYPE_NOSNIFF = True\nSECURE_BROWSER_XSS_FILTER = True\nX_FRAME_OPTIONS = \"DENY\"\n\n# CORS (django-cors-headers)\nCORS_ALLOWED_ORIGINS = os.environ.get(\"CORS_ORIGINS\", \"\").split(\",\")\nCORS_ALLOW_CREDENTIALS = True\n\n# CSP (django-csp)\nCSP_DEFAULT_SRC = (\"'self'\",)\nCSP_SCRIPT_SRC = (\"'self'\",)\nCSP_STYLE_SRC = (\"'self'\", \"'unsafe-inline'\")\nCSP_IMG_SRC = (\"'self'\", \"data:\", \"https:\")\n```\n\n### Permission Patterns\n\n```python\n# apps/core/permissions.py\nfrom rest_framework.permissions import BasePermission\n\nclass IsOwner(BasePermission):\n    \"\"\"Object-level: only the owner can access.\"\"\"\n    def has_object_permission(self, request, view, obj):\n        return obj.user == request.user\n\nclass IsAdminOrReadOnly(BasePermission):\n    def has_permission(self, request, view):\n        if request.method in (\"GET\", \"HEAD\", \"OPTIONS\"):\n            return True\n        return request.user.is_staff\n\nclass HasRole(BasePermission):\n    \"\"\"Role-based access control.\"\"\"\n    required_role = None\n    \n    def has_permission(self, request, view):\n        if not request.user.is_authenticated:\n            return False\n        return request.user.roles.filter(name=self.required_role).exists()\n\nclass IsManager(HasRole):\n    required_role = \"manager\"\n```\n\n### 10-Point Security Checklist\n\n| # | Check | How | Priority |\n|---|-------|-----|----------|\n| 1 | `manage.py check --deploy` | All warnings resolved | P0 |\n| 2 | `SECRET_KEY` from env/vault | Not in source code | P0 |\n| 3 | `DEBUG = False` in production | Env-specific settings | P0 |\n| 4 | HTTPS enforced | `SECURE_SSL_REDIRECT = True` | P0 |\n| 5 | CSRF protection enabled | Default — don't disable it | P0 |\n| 6 | SQL injection prevented | Always use ORM, never raw SQL with f-strings | P0 |\n| 7 | Input validation | Serializer validation on all inputs | P1 |\n| 8 | Rate limiting | DRF throttling configured | P1 |\n| 9 | Admin URL changed | Not `/admin/` — use random path | P1 |\n| 10 | Dependency audit | `pip-audit` or `safety check` in CI | P1 |\n\n---\n\n## Phase 5: Migrations & Database Management\n\n### Migration Safety Rules\n\n1. **Never edit a migration after it's been applied in production** — create a new one.\n2. **Always review auto-generated migrations** — `makemigrations` can produce destructive changes.\n3. **Add columns as nullable first** — `null=True` → deploy → backfill → make non-null.\n4. **Never rename columns directly** — add new, migrate data, remove old (3 deployments).\n5. **Use `RunPython` with `reverse_code`** — always make migrations reversible.\n6. **Squash periodically** — `squashmigrations app_name 0001 0050` for performance.\n7. **Lock table awareness** — `ALTER TABLE ADD COLUMN NOT NULL DEFAULT` locks the table in Postgres < 11.\n\n### Zero-Downtime Migration Pattern\n\n```python\n# Step 1: Add nullable column (safe, no lock)\n# migrations/0042_add_new_field.py\nclass Migration(migrations.Migration):\n    operations = [\n        migrations.AddField(\n            model_name=\"order\",\n            name=\"tracking_number\",\n            field=models.CharField(max_length=100, null=True, blank=True),\n        ),\n    ]\n\n# Step 2: Backfill data (separate migration)\n# migrations/0043_backfill_tracking.py\ndef backfill_tracking(apps, schema_editor):\n    Order = apps.get_model(\"orders\", \"Order\")\n    batch_size = 1000\n    while True:\n        ids = list(\n            Order.objects.filter(tracking_number__isnull=True)\n            .values_list(\"id\", flat=True)[:batch_size]\n        )\n        if not ids:\n            break\n        Order.objects.filter(id__in=ids).update(tracking_number=\"LEGACY\")\n\nclass Migration(migrations.Migration):\n    operations = [\n        migrations.RunPython(backfill_tracking, migrations.RunPython.noop),\n    ]\n\n# Step 3: Make non-null (after backfill verified)\n# migrations/0044_tracking_not_null.py\n```\n\n### Migration Conflict Resolution\n\n```bash\n# When two developers create migrations from same parent:\npython manage.py makemigrations --merge  # Creates merge migration\n\n# To detect conflicts in CI:\npython manage.py makemigrations --check --dry-run\n```\n\n---\n\n## Phase 6: Caching Strategy\n\n### Cache Hierarchy\n\n```python\n# config/settings/base.py\nCACHES = {\n    \"default\": {\n        \"BACKEND\": \"django_redis.cache.RedisCache\",\n        \"LOCATION\": os.environ.get(\"REDIS_URL\", \"redis://localhost:6379/0\"),\n        \"OPTIONS\": {\n            \"CLIENT_CLASS\": \"django_redis.client.DefaultClient\",\n            \"SERIALIZER\": \"django_redis.serializers.json.JSONSerializer\",\n        },\n        \"KEY_PREFIX\": \"myapp\",\n        \"TIMEOUT\": 300,  # 5 min default\n    }\n}\n\n# Session storage in Redis (faster than DB)\nSESSION_ENGINE = \"django.contrib.sessions.backends.cache\"\nSESSION_CACHE_ALIAS = \"default\"\n```\n\n### Caching Patterns\n\n```python\nfrom django.core.cache import cache\nfrom django.views.decorators.cache import cache_page\nfrom django.utils.decorators import method_decorator\n\n# View-level caching\n@cache_page(60 * 15)  # 15 minutes\ndef product_list(request):\n    ...\n\n# Manual cache with invalidation\ndef get_product_stats(product_id: str) -> dict:\n    cache_key = f\"product_stats:{product_id}\"\n    stats = cache.get(cache_key)\n    if stats is None:\n        stats = _compute_product_stats(product_id)\n        cache.set(cache_key, stats, timeout=600)\n    return stats\n\ndef invalidate_product_cache(product_id: str):\n    cache.delete(f\"product_stats:{product_id}\")\n\n# Signal-based cache invalidation\nfrom django.db.models.signals import post_save, post_delete\nfrom django.dispatch import receiver\n\n@receiver([post_save, post_delete], sender=Product)\ndef clear_product_cache(sender, instance, **kwargs):\n    invalidate_product_cache(str(instance.id))\n    cache.delete(\"product_list\")\n\n# Template fragment caching\n# {% load cache %}\n# {% cache 600 sidebar request.user.id %}\n#   ... expensive template fragment ...\n# {% endcache %}\n```\n\n### Cache Decision Guide\n\n| Data Type | Strategy | TTL | Invalidation |\n|---|---|---|---|\n| User session | Redis session backend | 2 weeks | On logout |\n| API list endpoint | `cache_page` | 5 min | Time-based |\n| Computed aggregations | Manual `cache.set` | 10-30 min | Signal on write |\n| Per-user dashboard | Manual with user key | 5 min | On user action |\n| Static config/settings | Manual, long TTL | 1 hour | On admin save |\n| Full-page (anonymous) | Nginx/CDN | 1-60 min | Purge API |\n\n---\n\n## Phase 7: Background Tasks (Celery)\n\n### Celery Configuration\n\n```python\n# config/celery.py\nimport os\nfrom celery import Celery\n\nos.environ.setdefault(\"DJANGO_SETTINGS_MODULE\", \"config.settings.production\")\napp = Celery(\"myapp\")\napp.config_from_object(\"django.conf:settings\", namespace=\"CELERY\")\napp.autodiscover_tasks()\n\n# config/settings/base.py\nCELERY_BROKER_URL = os.environ.get(\"CELERY_BROKER_URL\", \"redis://localhost:6379/1\")\nCELERY_RESULT_BACKEND = os.environ.get(\"CELERY_RESULT_BACKEND\", \"redis://localhost:6379/2\")\nCELERY_ACCEPT_CONTENT = [\"json\"]\nCELERY_TASK_SERIALIZER = \"json\"\nCELERY_RESULT_SERIALIZER = \"json\"\nCELERY_TIMEZONE = \"UTC\"\nCELERY_TASK_TRACK_STARTED = True\nCELERY_TASK_TIME_LIMIT = 300  # 5 min hard limit\nCELERY_TASK_SOFT_TIME_LIMIT = 240  # 4 min soft limit\nCELERY_TASK_ACKS_LATE = True  # Re-deliver if worker crashes\nCELERY_WORKER_PREFETCH_MULTIPLIER = 1  # Fair scheduling\n```\n\n### Task Patterns\n\n```python\n# apps/orders/tasks.py\nfrom celery import shared_task\nfrom celery.utils.log import get_task_logger\n\nlogger = get_task_logger(__name__)\n\n@shared_task(\n    bind=True,\n    max_retries=3,\n    default_retry_delay=60,\n    autoretry_for=(ConnectionError, TimeoutError),\n    retry_backoff=True,\n    retry_backoff_max=600,\n    acks_late=True,\n)\ndef send_order_confirmation(self, order_id: str):\n    \"\"\"Send confirmation email with exponential backoff retry.\"\"\"\n    try:\n        order = Order.objects.select_related(\"customer__user\").get(id=order_id)\n        send_email(\n            to=order.customer.user.email,\n            template=\"order_confirmation\",\n            context={\"order\": order},\n        )\n        logger.info(\"Confirmation sent\", extra={\"order_id\": order_id})\n    except Order.DoesNotExist:\n        logger.error(\"Order not found\", extra={\"order_id\": order_id})\n        # Don't retry — order doesn't exist\n\n@shared_task\ndef generate_daily_report():\n    \"\"\"Periodic task — scheduled via beat.\"\"\"\n    from apps.reports.services import build_daily_report\n    report = build_daily_report()\n    notify_admins(report)\n\n# Celery Beat schedule\nCELERY_BEAT_SCHEDULE = {\n    \"daily-report\": {\n        \"task\": \"apps.orders.tasks.generate_daily_report\",\n        \"schedule\": crontab(hour=6, minute=0),\n    },\n    \"cleanup-expired-sessions\": {\n        \"task\": \"apps.users.tasks.cleanup_sessions\",\n        \"schedule\": crontab(hour=3, minute=0),\n    },\n}\n```\n\n### 6 Celery Rules\n\n1. **Always pass IDs, not objects** — `task.delay(order.id)` not `task.delay(order)`. Objects can't serialize and may be stale.\n2. **Set time limits** — Every task needs `time_limit` to prevent zombies.\n3. **Make tasks idempotent** — They may run more than once (acks_late + crash = re-delivery).\n4. **Use `autoretry_for`** — Declarative retry for transient errors.\n5. **Separate queues** — Critical tasks (payments) on different queue than bulk (emails).\n6. **Monitor with Flower** — `celery -A config flower` for real-time task monitoring.\n\n---\n\n## Phase 8: Testing Strategy\n\n### Test Pyramid\n\n| Level | Tool | Target | Speed |\n|---|---|---|---|\n| Unit | pytest | Services, utils, models | <1s each |\n| Integration | pytest + Django test client | Views, serializers, DB | <5s each |\n| E2E | Playwright/Selenium | Full user flows | <30s each |\n| Contract | schemathesis/dredd | API schema compliance | <10s each |\n\n### Testing Patterns\n\n```python\n# conftest.py\nimport pytest\nfrom rest_framework.test import APIClient\n\n@pytest.fixture\ndef api_client():\n    return APIClient()\n\n@pytest.fixture\ndef authenticated_client(api_client, user):\n    api_client.force_authenticate(user=user)\n    return api_client\n\n@pytest.fixture\ndef user(db):\n    return User.objects.create_user(email=\"test@example.com\", password=\"testpass123\")\n\n@pytest.fixture\ndef order_factory(db):\n    def create(**kwargs):\n        defaults = {\"status\": \"pending\", \"amount\": 100}\n        defaults.update(kwargs)\n        if \"customer\" not in defaults:\n            defaults[\"customer\"] = CustomerFactory.create()\n        return Order.objects.create(**defaults)\n    return create\n\n# Test service layer\nclass TestCreateOrder:\n    def test_creates_order_with_items(self, db, customer, product):\n        order = create_order(\n            customer_id=customer.id,\n            items=[{\"product_id\": product.id, \"quantity\": 2}],\n        )\n        assert order.amount == product.price * 2\n        assert order.items.count() == 1\n        assert product.stock == Product.objects.get(id=product.id).stock  # Verify stock deducted\n\n    def test_rejects_insufficient_stock(self, db, customer, product):\n        product.stock = 0\n        product.save()\n        with pytest.raises(ValidationError, match=\"Insufficient stock\"):\n            create_order(\n                customer_id=customer.id,\n                items=[{\"product_id\": product.id, \"quantity\": 1}],\n            )\n\n# Test views\nclass TestOrderAPI:\n    def test_list_returns_only_user_orders(self, authenticated_client, user, order_factory):\n        my_order = order_factory(customer__user=user)\n        other_order = order_factory()  # Different user\n        \n        response = authenticated_client.get(\"/api/orders/\")\n        assert response.status_code == 200\n        ids = [o[\"id\"] for o in response.data[\"results\"]]\n        assert str(my_order.id) in ids\n        assert str(other_order.id) not in ids\n\n    def test_create_order_validates_items(self, authenticated_client):\n        response = authenticated_client.post(\"/api/orders/\", {\"items\": []}, format=\"json\")\n        assert response.status_code == 400\n```\n\n### 7 Testing Rules\n\n1. **Use `pytest-django`** — not Django's `TestCase`. Faster, better fixtures.\n2. **Use factories** — `factory_boy` or custom fixtures. Never seed test DB manually.\n3. **Test services, not views** — Business logic in services = easy to test without HTTP.\n4. **Use `@pytest.mark.django_db`** — Only tests that need DB should hit it.\n5. **Freeze time** — `freezegun` for time-dependent logic.\n6. **Mock external services** — `responses` for HTTP, `unittest.mock` for others.\n7. **CI runs `pytest --cov --cov-fail-under=80`** — Enforce coverage floor.\n\n---\n\n## Phase 9: Performance & Monitoring\n\n### Gunicorn Configuration\n\n```python\n# config/gunicorn.conf.py\nimport multiprocessing\n\nbind = \"0.0.0.0:8000\"\nworkers = multiprocessing.cpu_count() * 2 + 1\nworker_class = \"gthread\"  # or \"uvicorn.workers.UvicornWorker\" for async\nthreads = 4\nmax_requests = 1000\nmax_requests_jitter = 50\ntimeout = 30\ngraceful_timeout = 30\nkeepalive = 5\naccesslog = \"-\"\nerrorlog = \"-\"\nloglevel = \"info\"\n```\n\n### Django Middleware Order (Performance)\n\n```python\nMIDDLEWARE = [\n    \"django.middleware.security.SecurityMiddleware\",\n    \"whitenoise.middleware.WhiteNoiseMiddleware\",     # Static files (before everything)\n    \"django.contrib.sessions.middleware.SessionMiddleware\",\n    \"corsheaders.middleware.CorsMiddleware\",           # CORS (before CommonMiddleware)\n    \"django.middleware.common.CommonMiddleware\",\n    \"django.middleware.csrf.CsrfViewMiddleware\",\n    \"django.contrib.auth.middleware.AuthenticationMiddleware\",\n    \"apps.core.middleware.RequestIDMiddleware\",         # Custom: attach request ID\n    \"django.contrib.messages.middleware.MessageMiddleware\",\n    \"django.middleware.clickjacking.XFrameOptionsMiddleware\",\n]\n```\n\n### Structured Logging\n\n```python\n# config/settings/base.py\nLOGGING = {\n    \"version\": 1,\n    \"disable_existing_loggers\": False,\n    \"formatters\": {\n        \"json\": {\n            \"()\": \"pythonjsonlogger.jsonlogger.JsonFormatter\",\n            \"format\": \"%(asctime)s %(name)s %(levelname)s %(message)s\",\n        },\n    },\n    \"handlers\": {\n        \"console\": {\n            \"class\": \"logging.StreamHandler\",\n            \"formatter\": \"json\",\n        },\n    },\n    \"root\": {\"handlers\": [\"console\"], \"level\": \"INFO\"},\n    \"loggers\": {\n        \"django.db.backends\": {\"level\": \"WARNING\"},  # Quiet SQL logs\n        \"apps\": {\"level\": \"INFO\", \"propagate\": True},\n    },\n}\n```\n\n### Performance Targets\n\n| Metric | Target | How to Measure |\n|---|---|---|\n| p50 response time | <100ms | django-silk / APM |\n| p99 response time | <500ms | APM (Sentry, Datadog) |\n| DB queries per request | <10 | django-debug-toolbar |\n| Memory per worker | <256MB | Gunicorn + monitoring |\n| Celery task latency | <5s | Flower / Prometheus |\n\n---\n\n## Phase 10: Deployment\n\n### Production Dockerfile\n\n```dockerfile\n# Multi-stage build\nFROM python:3.12-slim AS builder\nRUN pip install --no-cache-dir uv\nWORKDIR /app\nCOPY requirements/production.txt .\nRUN uv pip install --system --no-cache -r production.txt\n\nFROM python:3.12-slim\nRUN adduser --disabled-password --no-create-home app\nWORKDIR /app\n\nCOPY --from=builder /usr/local/lib/python3.12 /usr/local/lib/python3.12\nCOPY --from=builder /usr/local/bin /usr/local/bin\nCOPY . .\n\nRUN python manage.py collectstatic --noinput\nUSER app\nEXPOSE 8000\nCMD [\"gunicorn\", \"config.wsgi:application\", \"-c\", \"config/gunicorn.conf.py\"]\n```\n\n### GitHub Actions CI/CD\n\n```yaml\nname: CI\non: [push, pull_request]\n\njobs:\n  test:\n    runs-on: ubuntu-latest\n    services:\n      postgres:\n        image: postgres:16\n        env:\n          POSTGRES_DB: test_db\n          POSTGRES_USER: test\n          POSTGRES_PASSWORD: test\n        ports: [\"5432:5432\"]\n      redis:\n        image: redis:7\n        ports: [\"6379:6379\"]\n    \n    steps:\n      - uses: actions/checkout@v4\n      - uses: actions/setup-python@v5\n        with: { python-version: \"3.12\" }\n      - run: pip install -r requirements/local.txt\n      - run: python manage.py check --deploy\n        env:\n          DJANGO_SETTINGS_MODULE: config.settings.local\n      - run: python manage.py makemigrations --check --dry-run\n      - run: pytest --cov --cov-fail-under=80 -n auto\n        env:\n          DATABASE_URL: postgres://test:test@localhost:5432/test_db\n          REDIS_URL: redis://localhost:6379/0\n      - run: ruff check .\n      - run: ruff format --check .\n      - run: mypy apps/\n```\n\n### Production Checklist\n\n**P0 — Must have before deploy:**\n- [ ] `manage.py check --deploy` passes with zero warnings\n- [ ] `SECRET_KEY` from environment variable\n- [ ] `DEBUG = False`\n- [ ] `ALLOWED_HOSTS` configured\n- [ ] HTTPS enforced\n- [ ] Database connection pooling\n- [ ] Static files served via WhiteNoise/CDN\n- [ ] Error tracking (Sentry) configured\n- [ ] Backups scheduled\n\n**P1 — Should have within first week:**\n- [ ] Rate limiting on all endpoints\n- [ ] Admin URL changed from `/admin/`\n- [ ] Cache backend configured (Redis)\n- [ ] Background tasks via Celery\n- [ ] Structured JSON logging\n- [ ] CI/CD pipeline\n- [ ] Health check endpoint\n- [ ] `pip-audit` in CI\n\n---\n\n## Phase 11: Common Patterns Library\n\n### Soft Delete Manager\n\n```python\nclass ActiveManager(models.Manager):\n    def get_queryset(self):\n        return super().get_queryset().filter(is_deleted=False)\n\nclass Order(SoftDeleteModel):\n    objects = ActiveManager()      # Default: excludes deleted\n    all_objects = models.Manager() # Include deleted\n```\n\n### Multi-Tenant Pattern\n\n```python\n# Middleware: set tenant from request\nclass TenantMiddleware:\n    def __init__(self, get_response):\n        self.get_response = get_response\n    \n    def __call__(self, request):\n        tenant_id = request.headers.get(\"X-Tenant-ID\")\n        if tenant_id:\n            request.tenant = Tenant.objects.get(id=tenant_id)\n        return self.get_response(request)\n\n# Auto-filter all queries by tenant\nclass TenantManager(models.Manager):\n    def get_queryset(self):\n        from threading import local\n        _thread_local = local()\n        qs = super().get_queryset()\n        tenant = getattr(_thread_local, \"tenant\", None)\n        if tenant:\n            qs = qs.filter(tenant=tenant)\n        return qs\n```\n\n### Webhook Handler\n\n```python\nimport hashlib, hmac\nfrom django.http import JsonResponse\nfrom django.views.decorators.csrf import csrf_exempt\nfrom django.views.decorators.http import require_POST\n\n@csrf_exempt\n@require_POST\ndef stripe_webhook(request):\n    payload = request.body\n    sig = request.headers.get(\"Stripe-Signature\")\n    \n    try:\n        event = stripe.Webhook.construct_event(payload, sig, settings.STRIPE_WEBHOOK_SECRET)\n    except (ValueError, stripe.error.SignatureVerificationError):\n        return JsonResponse({\"error\": \"Invalid signature\"}, status=400)\n    \n    handlers = {\n        \"checkout.session.completed\": handle_checkout,\n        \"invoice.paid\": handle_invoice_paid,\n        \"customer.subscription.deleted\": handle_cancellation,\n    }\n    \n    handler = handlers.get(event[\"type\"])\n    if handler:\n        handler(event[\"data\"][\"object\"])\n    \n    return JsonResponse({\"status\": \"ok\"})\n```\n\n---\n\n## Phase 12: Django 5.x Features\n\n### GeneratedField (Django 5.0+)\n\n```python\nclass Product(models.Model):\n    price = models.DecimalField(max_digits=10, decimal_places=2)\n    tax_rate = models.DecimalField(max_digits=4, decimal_places=2, default=0.20)\n    \n    total_price = models.GeneratedField(\n        expression=F(\"price\") * (1 + F(\"tax_rate\")),\n        output_field=models.DecimalField(max_digits=10, decimal_places=2),\n        db_persist=True,  # Stored column, not virtual\n    )\n```\n\n### Field Groups in Forms (Django 5.0+)\n\n```python\nclass ContactForm(forms.Form):\n    name = forms.CharField()\n    email = forms.EmailField()\n    \n    # Template: {{ form.as_field_group }}\n```\n\n### Database-Computed Default (Django 5.0+)\n\n```python\nfrom django.db.models.functions import Now\n\nclass Event(models.Model):\n    starts_at = models.DateTimeField(db_default=Now())\n```\n\n---\n\n## 10 Common Mistakes\n\n| # | Mistake | Fix |\n|---|---------|-----|\n| 1 | Not using custom User model | Always `AbstractUser` from Day 1 |\n| 2 | N+1 queries everywhere | `select_related` / `prefetch_related` |\n| 3 | Business logic in views | Move to `services.py` |\n| 4 | One settings file | Split: `base.py`, `local.py`, `production.py` |\n| 5 | No migration review | Always read auto-generated migrations |\n| 6 | `DEBUG = True` in production | Env-specific settings, never conditional |\n| 7 | Synchronous email sending | Celery task for all I/O |\n| 8 | No connection pooling | pgbouncer or django-db-conn-pool |\n| 9 | Raw SQL with f-strings | ORM or parameterized queries only |\n| 10 | No request timeouts | Gunicorn `timeout` + DB `statement_timeout` |\n\n---\n\n## Quality Rubric (0-100)\n\n| Dimension | Weight | Criteria |\n|---|---|---|\n| Architecture | 15% | Settings split, service layer, app structure |\n| ORM Usage | 15% | No N+1, bulk ops, proper indexes |\n| Security | 15% | `check --deploy`, HTTPS, auth, CSRF |\n| Testing | 15% | >80% coverage, pytest, factories |\n| Performance | 10% | Caching, connection pooling, query count |\n| Error Handling | 10% | Structured errors, Sentry, logging |\n| Migrations | 10% | Reversible, zero-downtime, reviewed |\n| Deployment | 10% | Docker, CI/CD, health checks |\n\n**90-100**: Production-grade, enterprise-ready\n**70-89**: Solid, needs minor hardening\n**50-69**: Functional but risky at scale\n**Below 50**: Technical debt crisis — stop features, fix foundations\n\n---\n\n## 10 Commandments of Production Django\n\n1. Custom User model from the first `makemigrations`.\n2. Fat services, thin views. Always.\n3. `select_related` and `prefetch_related` on every queryset with relations.\n4. Settings split by environment. No `if DEBUG`.\n5. Every migration reviewed by a human before merge.\n6. Celery for anything that takes >200ms.\n7. `manage.py check --deploy` in CI. Zero warnings.\n8. Connection pooling. Always.\n9. Test services, not implementation details.\n10. If it's not in `requirements.txt`, it doesn't exist.\n\n---\n\n## Natural Language Commands\n\n- \"Review this Django project\" → Run Quick Health Check, score /8\n- \"Optimize these queries\" → Apply N+1 prevention patterns, suggest indexes\n- \"Set up DRF for this model\" → Generate serializers + views + URLs + tests\n- \"Add Celery task for X\" → Task with retry, time limit, idempotency\n- \"Review this migration\" → Check safety rules, suggest zero-downtime approach\n- \"Set up authentication\" → JWT + custom user + permissions\n- \"Production checklist\" → Run full P0/P1 audit\n- \"Add caching for X\" → Pick strategy from cache decision guide\n- \"Set up CI/CD\" → GitHub Actions + pytest + ruff + mypy\n- \"Create service for X\" → Service layer with validation + transaction\n- \"Set up logging\" → Structured JSON + request ID middleware\n- \"Deploy this Django app\" → Dockerfile + gunicorn + checklist\n","readmeExcerpt":"Django Production Engineering Complete methodology for building, scaling, and operating production Django applications. From project structure to deployment, security to performance — every decision framework a Django team needs. Quick Health Check Run this 8-signal triage on any Django project: | # | Signal | Check | Healthy | |---|--------|-------|---------| | 1 | Settings split | settings/base.py, local.py, produc","codeSnippets":[],"executableExamples":[{"language":"text","snippet":"myproject/\n├── config/                    # Project config (was myproject/)\n│   ├── __init__.py\n│   ├── settings/\n│   │   ├── __init__.py\n│   │   ├── base.py           # Shared settings\n│   │   ├── local.py          # Development\n│   │   ├── staging.py        # Staging\n│   │   └── production.py     # Production\n│   ├── urls.py               # Root URL conf\n│   ├── wsgi.py\n│   ├── asgi.py\n│   └── celery.py             # Celery app\n├── apps/\n│   ├── users/                # Custom user model (ALWAYS)\n│   │   ├── models.py\n│   │   ├── managers.py\n│   │   ├── admin.py\n│   │   ├── serializers.py\n│   │   ├── views.py\n│   │   ├── urls.py\n│   │   ├── services.py       # Business logic\n│   │   ├── selectors.py      # Complex queries\n│   │   ├── tests/\n│   │   │   ├── test_models.py\n│   │   │   ├── test_views.py\n│   │   │   └── test_services.py\n│   │   └── migrations/\n│   ├── core/                 # Shared utilities\n│   │   ├── models.py         # Abstract base models\n│   │   ├── permissions.py\n│   │   ├── pagination.py\n│   │   ├── exceptions.py\n│   │   └── middleware.py\n│   └── <domain>/             # Feature apps\n├── templates/\n├── static/\n├── media/\n├── requirements/\n│   ├── base.txt\n│   ├── local.txt\n│   └── production.txt\n├── docker/\n├── scripts/\n├── manage.py\n├── pyproject.toml\n├── Makefile\n└── .env.example"},{"language":"python","snippet":"# apps/core/models.py\nimport uuid\nfrom django.db import models\n\nclass TimeStampedModel(models.Model):\n    created_at = models.DateTimeField(auto_now_add=True, db_index=True)\n    updated_at = models.DateTimeField(auto_now=True)\n\n    class Meta:\n        abstract = True\n\nclass UUIDModel(models.Model):\n    id = models.UUIDField(primary_key=True, default=uuid.uuid4, editable=False)\n\n    class Meta:\n        abstract = True\n\nclass SoftDeleteModel(models.Model):\n    is_deleted = models.BooleanField(default=False, db_index=True)\n    deleted_at = models.DateTimeField(null=True, blank=True)\n\n    class Meta:\n        abstract = True\n\n    def soft_delete(self):\n        from django.utils import timezone\n        self.is_deleted = True\n        self.deleted_at = timezone.now()\n        self.save(update_fields=[\"is_deleted\", \"deleted_at\"])"},{"language":"python","snippet":"# ❌ N+1 — fires 1 + N queries\nfor order in Order.objects.all():\n    print(order.customer.name)        # Each access = new query\n    for item in order.items.all():    # Each access = new query\n        print(item.product.name)      # Each access = new query\n\n# ✅ Optimized — fires 3 queries total\norders = (\n    Order.objects\n    .select_related(\"customer\")              # FK/OneToOne — JOIN\n    .prefetch_related(\n        Prefetch(\n            \"items\",\n            queryset=OrderItem.objects\n                .select_related(\"product\")   # Nested FK\n                .only(\"id\", \"quantity\", \"product__name\")  # Only needed fields\n        )\n    )\n)"},{"language":"python","snippet":"# QuerySets are LAZY — no database hit until evaluated\nqs = Order.objects.filter(status=\"pending\")  # No query yet\n\n# These EVALUATE the queryset (trigger SQL):\nlist(qs)           # Iteration\nlen(qs)            # Use qs.count() instead\nbool(qs)           # Use qs.exists() instead\nqs[0]              # Indexing\nrepr(qs)           # In shell/debugger\nfor obj in qs:     # Iteration\nif qs:             # Use qs.exists()"},{"language":"python","snippet":"# ❌ N queries\nfor item in items:\n    Product.objects.create(name=item[\"name\"], price=item[\"price\"])\n\n# ✅ 1 query\nProduct.objects.bulk_create(\n    [Product(name=i[\"name\"], price=i[\"price\"]) for i in items],\n    batch_size=1000,\n    ignore_conflicts=True,  # Skip duplicates\n)\n\n# ✅ Bulk update\nProduct.objects.filter(category=\"sale\").update(\n    price=F(\"price\") * 0.9  # 10% discount — single query, no race conditions\n)\n\n# ✅ Bulk update with different values\nproducts = Product.objects.filter(id__in=ids)\nfor p in products:\n    p.price = new_prices[p.id]\nProduct.objects.bulk_update(products, [\"price\"], batch_size=1000)"},{"language":"python","snippet":"from django.db.models import F, Q, Value, Count, Avg, Sum, Case, When\nfrom django.db.models.functions import Coalesce, Lower, TruncMonth\n\n# Conditional aggregation\nOrder.objects.aggregate(\n    total_revenue=Sum(\"amount\"),\n    paid_revenue=Sum(\"amount\", filter=Q(status=\"paid\")),\n    refund_count=Count(\"id\", filter=Q(status=\"refunded\")),\n    avg_order_value=Avg(\"amount\", filter=Q(status=\"paid\")),\n)\n\n# Annotate with computed fields\ncustomers = (\n    Customer.objects\n    .annotate(\n        order_count=Count(\"orders\"),\n        total_spent=Coalesce(Sum(\"orders__amount\"), Value(0)),\n        last_order=Max(\"orders__created_at\"),\n    )\n    .filter(order_count__gte=5)\n    .order_by(\"-total_spent\")\n)\n\n# Monthly revenue report\nmonthly = (\n    Order.objects\n    .filter(status=\"paid\")\n    .annotate(month=TruncMonth(\"created_at\"))\n    .values(\"month\")\n    .annotate(\n        revenue=Sum(\"amount\"),\n        count=Count(\"id\"),\n        avg=Avg(\"amount\"),\n    )\n    .order_by(\"month\")\n)\n\n# Case/When for computed status\nusers = User.objects.annotate(\n    tier=Case(\n        When(total_spent__gte=10000, then=Value(\"platinum\")),\n        When(total_spent__gte=5000, then=Value(\"gold\")),\n        When(total_spent__gte=1000, then=Value(\"silver\")),\n        default=Value(\"bronze\"),\n    )\n)"}],"parameters":{},"dependencies":[],"permissions":[],"extractedFiles":[],"languages":["typescript"],"docsSourceLabel":"CLAWHUB","editorialOverview":"Django Production Engineering Django Production Engineering Complete methodology for building, scaling, and operating production Django applications. From project structure to deployment, security to performance — every decision framework a Django team needs. Quick Health Check Run this 8-signal triage on any Django project: | # | Signal | Check | Healthy | |---|--------|-------|---------| | 1 | Settings split | settings/base.py, local.py, produc","editorialQuality":{"score":100,"threshold":65,"status":"ready","wordCount":364,"uniquenessScore":67,"reasons":[]}},"media":{"evidence":{"source":"no-media","verified":false,"confidence":"low","updatedAt":"2026-04-15T00:45:39.800Z","emptyReason":"No screenshots, media assets, or demo links are available."},"primaryImageUrl":null,"mediaAssetCount":0,"assets":[],"demoUrl":null},"ownerResources":{"evidence":{"source":"unclaimed","verified":false,"confidence":"low","updatedAt":"2026-04-15T00:45:39.800Z","emptyReason":"This page has not been claimed by the agent owner."},"hasCustomPage":false,"customPageUpdatedAt":null,"customLinks":[],"structuredLinks":{"docsUrl":null,"demoUrl":null,"supportUrl":null,"pricingUrl":null,"statusUrl":null},"customPage":null},"relatedAgents":{"evidence":{"source":"protocol-neighbors","verified":false,"confidence":"medium","updatedAt":"2026-10-10T04:24:15.923Z","emptyReason":null},"items":[{"id":"8ebccd8e-3863-4187-8355-c3f14e1f9edf","entityType":"agent","canonicalPath":"/agent/iofficeai-aionui","slug":"iofficeai-aionui","name":"AionUi","description":"Free, local, open-source 24/7 Cowork app and OpenClaw for Gemini CLI, Claude Code, Codex, OpenCode, Qwen Code, Goose CLI, Auggie, and more | 🌟 Star if you like it!","url":"https://github.com/iOfficeAI/AionUi","homepage":"https://www.aionui.com","source":"GITHUB_REPOS","protocols":["MCP","OPENCLAW"],"capabilities":[],"safetyScore":100,"overallRank":70,"updatedAt":"2026-10-09T19:11:12.944Z","createdAt":"2026-02-25T03:38:16.584Z","downloads":null},{"id":"b917f68a-ebff-438e-84f8-3f4b2494c0bc","entityType":"agent","canonicalPath":"/agent/activepieces-activepieces","slug":"activepieces-activepieces","name":"activepieces","description":"AI Agents & MCPs & AI Workflow Automation • (~400 MCP servers for AI agents) • AI Automation / AI Agent with MCPs • AI Workflows & AI Agents • MCPs for AI Agents","url":"https://github.com/activepieces/activepieces","homepage":"https://www.activepieces.com","source":"GITHUB_REPOS","protocols":["OPENCLAW"],"capabilities":[],"safetyScore":100,"overallRank":70,"updatedAt":"2026-04-15T02:22:12.426Z","createdAt":"2026-02-25T03:38:12.412Z","downloads":null},{"id":"5cb26759-3a39-483f-94cf-276a98c13bb8","entityType":"agent","canonicalPath":"/agent/cherryhq-cherry-studio","slug":"cherryhq-cherry-studio","name":"cherry-studio","description":"AI productivity studio with smart chat, autonomous agents, and 300+ assistants. Unified access to frontier LLMs","url":"https://github.com/CherryHQ/cherry-studio","homepage":"https://cherry-ai.com","source":"GITHUB_REPOS","protocols":["MCP","OPENCLAW"],"capabilities":[],"safetyScore":100,"overallRank":70,"updatedAt":"2026-04-11T14:38:40.986Z","createdAt":"2026-02-25T03:38:19.379Z","downloads":null},{"id":"6f6582d0-5d76-4f0f-b81d-86520247950b","entityType":"agent","canonicalPath":"/agent/copilotkit-copilotkit","slug":"copilotkit-copilotkit","name":"CopilotKit","description":"The Frontend for Agents & Generative UI. React + Angular","url":"https://github.com/CopilotKit/CopilotKit","homepage":"https://docs.copilotkit.ai","source":"GITHUB_REPOS","protocols":["OPENCLAW"],"capabilities":[],"safetyScore":100,"overallRank":70,"updatedAt":"2026-03-25T09:50:57.846Z","createdAt":"2026-02-25T03:39:14.617Z","downloads":null}],"links":{"hub":"/agent","source":"/agent/source/clawhub","protocols":[{"label":"OpenClaw","href":"/agent/protocol/openclew"}]}}}