django

Django Framework Guide

Safety Notice

This listing is imported from skills.sh public index metadata. Review upstream SKILL.md and repository scripts before running.

Copy this and send it to your AI assistant to learn

Install skill "django" with this command: npx skills add ar4mirez/samuel/ar4mirez-samuel-django

Django Framework Guide

Applies to: Django 5+, Django REST Framework, Django Channels Language: Python 3.10+

Core Principles

  • Batteries Included: Leverage Django's built-in features before adding third-party packages

  • DRY: Don't Repeat Yourself -- use abstract models, mixins, and shared utilities

  • Fat Models, Thin Views: Keep business logic in models and services, not views

  • Explicit Over Implicit: Use clear URL patterns, explicit imports, named relationships

  • Security by Default: CSRF, XSS protection, SQL injection prevention are built in

When to Use Django

Good fit:

  • Full-stack web applications with templates

  • Admin interface needed out of the box

  • Content management systems

  • Session-based authentication

  • ORM with built-in migrations

Consider alternatives:

  • Pure APIs with async-first needs (FastAPI)

  • Minimal framework overhead (Flask)

  • Real-time heavy workloads without Channels

Project Structure

myproject/ ├── manage.py ├── pyproject.toml ├── requirements/ │ ├── base.txt │ ├── dev.txt │ └── prod.txt ├── config/ # Project configuration │ ├── init.py │ ├── settings/ │ │ ├── init.py │ │ ├── base.py │ │ ├── dev.py │ │ └── prod.py │ ├── urls.py │ ├── wsgi.py │ └── asgi.py ├── apps/ # Django applications │ ├── users/ │ │ ├── init.py │ │ ├── admin.py │ │ ├── apps.py │ │ ├── models.py │ │ ├── views.py │ │ ├── urls.py │ │ ├── forms.py │ │ ├── serializers.py # If using DRF │ │ ├── services.py # Business logic │ │ └── tests/ │ │ ├── init.py │ │ ├── test_models.py │ │ ├── test_views.py │ │ └── test_services.py │ └── core/ # Shared utilities │ ├── init.py │ ├── models.py # Abstract base models │ └── mixins.py ├── templates/ │ ├── base.html │ └── components/ ├── static/ │ ├── css/ │ └── js/ └── tests/ └── conftest.py

  • Split settings into base.py , dev.py , prod.py

  • Group apps under apps/ directory

  • Keep core/ app for shared abstract models and utilities

  • Place business logic in services.py , not in views

  • Co-locate tests inside each app under tests/ directory

Guardrails

Settings

  • Never hardcode SECRET_KEY -- use python-decouple or environment variables

  • Split settings: base.py (shared), dev.py (debug), prod.py (secure)

  • Always define AUTH_USER_MODEL before first migration

  • Set DEFAULT_AUTO_FIELD = "django.db.models.BigAutoField"

  • Use ALLOWED_HOSTS in production (never ["*"] )

Models

  • Always define str on every model

  • Always set class Meta with db_table , ordering , and indexes

  • Use abstract base models for shared fields (TimeStampedModel , UUIDModel )

  • Use TextChoices /IntegerChoices for status fields (not raw strings)

  • Add related_name to all ForeignKey and OneToOneField relationships

  • Use on_delete explicitly: CASCADE , PROTECT , SET_NULL , SET_DEFAULT

  • Add database indexes for frequently queried fields

  • Use validators at model level for domain constraints

Abstract Base Models

apps/core/models.py

from django.db import models import uuid

class TimeStampedModel(models.Model): """Abstract base with created/updated timestamps.""" created_at = models.DateTimeField(auto_now_add=True) updated_at = models.DateTimeField(auto_now=True)

class Meta:
    abstract = True

class UUIDModel(models.Model): """Abstract base with UUID primary key.""" id = models.UUIDField( primary_key=True, default=uuid.uuid4, editable=False )

class Meta:
    abstract = True

Custom User Model

  • Always create a custom user model before the first migration

  • Extend AbstractUser (not AbstractBaseUser unless you need full control)

  • Set AUTH_USER_MODEL = "users.User" in settings

apps/users/models.py

from django.contrib.auth.models import AbstractUser from django.db import models from apps.core.models import TimeStampedModel, UUIDModel

class User(AbstractUser, UUIDModel, TimeStampedModel): email = models.EmailField(unique=True) USERNAME_FIELD = "email" REQUIRED_FIELDS = ["username"]

class Meta:
    db_table = "users"
    ordering = ["-created_at"]
    indexes = [models.Index(fields=["email"])]

def __str__(self) -> str:
    return self.email

Views and URLs

Class-Based Views (CBVs)

  • Use ListView , DetailView , CreateView , UpdateView for CRUD

  • Use LoginRequiredMixin for authenticated views

  • Override get_queryset() to add filtering and select_related /prefetch_related

  • Override form_valid() to inject the current user

from django.views.generic import ListView from django.db.models import Q from .models import Product

class ProductListView(ListView): model = Product template_name = "products/list.html" context_object_name = "products" paginate_by = 20

def get_queryset(self):
    qs = Product.objects.filter(
        status=Product.Status.PUBLISHED
    )
    search = self.request.GET.get("q")
    if search:
        qs = qs.filter(
            Q(name__icontains=search)
            | Q(description__icontains=search)
        )
    return qs.select_related("category")

URL Configuration

config/urls.py

from django.contrib import admin from django.urls import path, include

urlpatterns = [ path("admin/", admin.site.urls), path("api/", include("apps.api.urls")), path("", include("apps.products.urls")), ]

  • Use include() for app-level URL namespaces

  • Use app_name in each app's urls.py for reverse resolution

  • Serve media files in DEBUG mode only

ORM Essentials

Query Optimization

  • Always use select_related() for ForeignKey/OneToOne (SQL JOIN)

  • Always use prefetch_related() for ManyToMany/reverse FK (separate query)

  • Use only() or defer() to limit fields when not all columns needed

  • Never call Model.objects.all() without pagination or limits

  • Use F() expressions for database-level operations

  • Use Q() objects for complex lookups

Avoiding N+1 Queries

BAD: N+1 queries

for product in Product.objects.all(): print(product.category.name) # Extra query per product

GOOD: Single JOIN query

for product in Product.objects.select_related("category"): print(product.category.name) # No extra queries

Transactions

  • Use @transaction.atomic for multi-step writes

  • Use select_for_update() for optimistic locking

from django.db import transaction

@transaction.atomic def transfer_stock(source_id, dest_id, qty): source = Product.objects.select_for_update().get(id=source_id) dest = Product.objects.select_for_update().get(id=dest_id) source.stock -= qty dest.stock += qty source.save(update_fields=["stock"]) dest.save(update_fields=["stock"])

Admin Configuration

from django.contrib import admin from .models import Product

@admin.register(Product) class ProductAdmin(admin.ModelAdmin): list_display = ["name", "category", "price", "status"] list_filter = ["status", "category", "created_at"] search_fields = ["name", "description"] prepopulated_fields = {"slug": ("name",)} readonly_fields = ["created_at", "updated_at"] ordering = ["-created_at"]

fieldsets = (
    (None, {"fields": ("name", "slug", "description")}),
    ("Pricing", {"fields": ("price", "stock")}),
    ("Classification", {"fields": ("category", "status")}),
    ("Timestamps", {
        "fields": ("created_at", "updated_at"),
        "classes": ("collapse",),
    }),
)
  • Always register models with @admin.register(Model)

  • Use list_display for useful columns, list_filter for filtering

  • Use prepopulated_fields for slug generation

  • Group fields with fieldsets for organized admin forms

Django REST Framework (DRF)

Settings

REST_FRAMEWORK = { "DEFAULT_AUTHENTICATION_CLASSES": [ "rest_framework.authentication.SessionAuthentication", "rest_framework_simplejwt.authentication.JWTAuthentication", ], "DEFAULT_PERMISSION_CLASSES": [ "rest_framework.permissions.IsAuthenticated", ], "DEFAULT_PAGINATION_CLASS": ( "rest_framework.pagination.PageNumberPagination" ), "PAGE_SIZE": 20, "DEFAULT_THROTTLE_RATES": { "anon": "100/hour", "user": "1000/hour", }, }

ViewSets and Routers

  • Use ModelViewSet for full CRUD

  • Use @action(detail=True/False) for custom endpoints

  • Override get_serializer_class() for different read/write serializers

  • Override get_queryset() to add select_related /prefetch_related

from rest_framework import viewsets from rest_framework.decorators import action from rest_framework.response import Response

class ProductViewSet(viewsets.ModelViewSet): queryset = Product.objects.select_related("category") permission_classes = [IsAuthenticatedOrReadOnly]

def get_serializer_class(self):
    if self.action in ["create", "update", "partial_update"]:
        return ProductCreateSerializer
    return ProductSerializer

def perform_create(self, serializer):
    serializer.save(created_by=self.request.user)

@action(detail=True, methods=["post"])
def publish(self, request, pk=None):
    product = self.get_object()
    product.status = Product.Status.PUBLISHED
    product.save(update_fields=["status"])
    return Response({"status": "published"})

Serializers

  • Use ModelSerializer for standard CRUD

  • Add read_only_fields for computed/auto fields

  • Validate in validate_<field>() or validate() methods

  • Use nested serializers for read, flat IDs for write

Security Essentials

  • CSRF: Enabled by default for forms; use @csrf_exempt sparingly

  • XSS: Django templates auto-escape by default; never use |safe with user data

  • SQL Injection: ORM uses parameterized queries; never use raw SQL with string formatting

  • Clickjacking: X-Frame-Options middleware enabled by default

  • HTTPS: Set SECURE_SSL_REDIRECT = True in production

  • HSTS: Set SECURE_HSTS_SECONDS in production

  • Cookies: Set SESSION_COOKIE_SECURE = True and CSRF_COOKIE_SECURE = True

  • Passwords: Use AUTH_PASSWORD_VALIDATORS (enabled by default)

  • CORS: Use django-cors-headers with explicit allowed origins (never CORS_ALLOW_ALL_ORIGINS in production)

Testing

Standards

  • Use pytest with pytest-django (not Django's built-in test runner)

  • Mark database tests with @pytest.mark.django_db

  • Use factory-boy or fixtures for test data

  • Use APIClient for DRF endpoint testing

  • Coverage target: >80% for business logic

  • Test file naming: test_models.py , test_views.py , test_services.py

Fixtures

conftest.py

import pytest from rest_framework.test import APIClient from apps.users.models import User

@pytest.fixture def api_client(): return APIClient()

@pytest.fixture def user(db): return User.objects.create_user( username="testuser", email="test@example.com", password="testpass123", )

@pytest.fixture def authenticated_client(api_client, user): api_client.force_authenticate(user=user) return api_client

Commands Reference

Development

python manage.py runserver python manage.py shell_plus # django-extensions

Migrations

python manage.py makemigrations python manage.py migrate python manage.py showmigrations

Testing

pytest pytest -v --cov=apps --cov-report=html pytest apps/products/ -k "test_create"

Database

python manage.py dbshell python manage.py dumpdata products > fixtures/products.json python manage.py loaddata fixtures/products.json

Static files

python manage.py collectstatic

Celery

celery -A config worker -l info celery -A config beat -l info

Dependencies

Base: Django>=5.0 , djangorestframework , django-cors-headers , django-filter , djangorestframework-simplejwt , python-decouple , psycopg2-binary , whitenoise

Dev: pytest , pytest-django , pytest-cov , factory-boy , django-debug-toolbar , django-extensions , black , ruff , mypy , django-stubs

Best Practices

Do

  • Use select_related and prefetch_related for every queryset

  • Create indexes for frequently queried fields

  • Use @transaction.atomic for multi-step operations

  • Validate at both model level and serializer level

  • Write services for business logic (not in views)

  • Use signals sparingly (prefer explicit service calls)

  • Cache expensive queries with Django cache framework

  • Use environment variables for all configuration

Don't

  • Put business logic in views

  • Use raw SQL without parameterization

  • Ignore N+1 query problems

  • Store sensitive data in settings files

  • Use Model.objects.all() without limits

  • Skip migrations in production

  • Use CORS_ALLOW_ALL_ORIGINS = True in production

  • Use |safe template filter with user-provided data

Advanced Topics

For detailed code examples and advanced patterns, see:

  • references/patterns.md -- DRF serializers, middleware, services, signals, Celery tasks, management commands, deployment, and testing patterns

External References

  • Django Documentation

  • Django REST Framework

  • Two Scoops of Django

  • Django Best Practices

Source Transparency

This detail page is rendered from real SKILL.md content. Trust labels are metadata-based hints, not a safety guarantee.

Related Skills

Related by shared tags or category signals.

General

actix-web

No summary provided by upstream source.

Repository SourceNeeds Review
General

frontend-design

No summary provided by upstream source.

Repository SourceNeeds Review
General

blazor

No summary provided by upstream source.

Repository SourceNeeds Review
General

fastapi

No summary provided by upstream source.

Repository SourceNeeds Review