Django Summary

Django has many moving parts. This post is a reference for the patterns you use repeatedly: models, views, templates, the ORM, migrations, the admin panel, and DRF.

TL;DR: A Django reference covering models, ORM queries, views, URLs, templates, migrations, admin, and Django REST Framework basics.
Stack: Python, Django, Django REST Framework
Level: Beginner
Reading time: ~15 min

Install Django, create project and app

pip install django
django-admin startproject myproject .
python manage.py startapp myapp

Configure database connection

# Install driver for PostgreSQL (Ubuntu)
sudo apt-get install libpq-dev
pip install psycopg2-binary

# settings.py
DATABASES = {
    'default': {
        'ENGINE': 'django.db.backends.postgresql',
        'NAME': 'postgres',
        'USER': 'admin',
        'PASSWORD': '123456',
        'HOST': 'localhost',
        'PORT': '5432',
    }
}

# Run migrations
python3 manage.py makemigrations
python3 manage.py migrate
python manage.py createsuperuser

Django REST Framework

pip install djangorestframework

# settings.py
INSTALLED_APPS = [
    ...
    'rest_framework',
]

View (APIView)

from rest_framework.response import Response
from rest_framework import status
from rest_framework.views import APIView
from application.use_cases.add_instrument.add_instrument import AddInstrument
from application.use_cases.add_instrument.protocols.add_instrument_request import AddInstrumentRequest

class AddInstrumentView(APIView):
    def post(self, request):
        name = request.data.get('name')
        if name is None:
            return Response({"message": "name is required"}, status=status.HTTP_400_BAD_REQUEST)

        use_case_request = AddInstrumentRequest(name=name)
        use_case = AddInstrument()
        use_case_response = use_case.execute(use_case_request)
        return Response({"name": use_case_response.name}, status=status.HTTP_200_OK)

Use case and protocols

from app.models import Instrument
from application.use_cases.add_instrument.protocols.add_instrument_request import AddInstrumentRequest

class AddInstrument:
    def execute(self, request: AddInstrumentRequest):
        instrument = Instrument.objects.create(name=request.name)
        return instrument

class AddInstrumentRequest:
    def __init__(self, name: str):
        self.name = name

class AddInstrumentResponse:
    def __init__(self, name: str):
        self.name = name

Routes

# project/urls.py
urlpatterns = [
    path("admin/", admin.site.urls),
    path('api/', include('presentation.urls')),
]

# presentation/urls.py
urlpatterns = [
    path('add-instrument', AddInstrumentView.as_view()),
    path('list-instruments', ListInstrumentView.as_view()),
]

JWT Authentication

pip install djangorestframework-simplejwt

# settings.py
REST_FRAMEWORK = {
    "DEFAULT_AUTHENTICATION_CLASSES": (
        "rest_framework_simplejwt.authentication.JWTAuthentication",
    ),
}

SIMPLE_JWT = {
    "ACCESS_TOKEN_LIFETIME": timedelta(days=1),
    "REFRESH_TOKEN_LIFETIME": timedelta(days=1),
    "ROTATE_REFRESH_TOKENS": True,
    "BLACKLIST_AFTER_ROTATION": True,
    "AUTH_HEADER_TYPES": ("Bearer",),
}

What you’ve built

A complete Django reference covering the framework from models to deployment-ready patterns. Come back here when you need to look up a specific Django pattern quickly.

Next steps

  • Use select_related() for ForeignKey and OneToOne relationships to avoid N+1 queries, and prefetch_related() for ManyToMany and reverse ForeignKey.
  • Use Django signals (post_save, pre_delete) for side effects that should happen after model operations, keeping views and business logic clean.
  • Enable Django Debug Toolbar in development to see all SQL queries per request. Most Django performance issues are database-related.

Questions or feedback? Find me on LinkedIn or GitHub.

Leave a Comment