skip to content

django β€” Full-Stack Web Framework

Build database-driven web applications with Django. Covers project setup, models, migrations, the admin panel, views, and the management command workflow.

3 min read 14 snippets yesterday deep dive

django β€” Full-Stack Web Framework#

What it is#

Django is a batteries-included web framework: ORM, migrations, admin panel, authentication, form handling, and template engine all come built-in. It follows the MTV (Model–Template–View) pattern and enforces a project layout that scales from a simple blog to a large multi-app system.

Install#

pip install django

Create a project and app#

django-admin startproject mysite
cd mysite
python manage.py startapp blog

Output:

(no output β€” creates directory structure)

Generated structure:

mysite/
β”œβ”€β”€ manage.py
β”œβ”€β”€ mysite/
β”‚   β”œβ”€β”€ __init__.py
β”‚   β”œβ”€β”€ settings.py
β”‚   β”œβ”€β”€ urls.py
β”‚   └── wsgi.py
└── blog/
    β”œβ”€β”€ models.py
    β”œβ”€β”€ views.py
    β”œβ”€β”€ admin.py
    └── migrations/

Define a model#

# blog/models.py
from django.db import models

class Post(models.Model):
    title = models.CharField(max_length=200)
    body = models.TextField()
    published = models.BooleanField(default=False)
    created_at = models.DateTimeField(auto_now_add=True)

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

Run migrations#

# Add 'blog' to INSTALLED_APPS in mysite/settings.py first
python manage.py makemigrations
python manage.py migrate

Output:

Migrations for 'blog':
  blog/migrations/0001_initial.py
    - Create model Post

Operations to perform:
  Apply all migrations: admin, auth, blog, contenttypes, sessions
Running migrations:
  Applying blog.0001_initial... OK

Register in admin and create superuser#

# blog/admin.py
from django.contrib import admin
from .models import Post

@admin.register(Post)
class PostAdmin(admin.ModelAdmin):
    list_display = ["title", "published", "created_at"]
    list_filter = ["published"]
    search_fields = ["title", "body"]
python manage.py createsuperuser
python manage.py runserver

Output:

Username: admin
Email address: admin@example.com
Password: β€’β€’β€’β€’β€’β€’β€’β€’
Superuser created successfully.

Watching for file changes with StatReloader
Django version 5.1.0, using settings 'mysite.settings'
Starting development server at http://127.0.0.1:8000/

Browse to http://127.0.0.1:8000/admin/ to log in and manage Post records.

When / why to use it#

  • Full web applications that need user auth, admin panel, and a built-in ORM.
  • Content-heavy sites (CMS, blogs, e-commerce).
  • Teams that want strong conventions and a large ecosystem of third-party apps (django-rest-framework, django-allauth, etc.).

Prefer Flask for small APIs with no admin requirements. Prefer FastAPI for async, high-performance APIs.

Common pitfalls#

[!WARNING] Never run manage.py runserver in production β€” it is single-threaded and not hardened. Use gunicorn + nginx or a managed platform (Railway, Fly.io, Heroku).

[!WARNING] DEBUG = True in production β€” Django shows full tracebacks with local variable values in the browser when DEBUG=True. Set DEBUG=False and ALLOWED_HOSTS correctly in production, and use environment variables for secret settings.

[!WARNING] Migration conflicts in teams β€” when two developers add different migrations, you get a conflict. Resolve with: python manage.py makemigrations --merge.

[!TIP] Use python manage.py shell_plus (from django-extensions) instead of manage.py shell β€” it auto-imports all models.

Richer example β€” class-based view with JSON response#

# blog/views.py
from django.http import JsonResponse
from django.views import View
from .models import Post

class PostListView(View):
    def get(self, request):
        posts = list(
            Post.objects.filter(published=True)
            .values("id", "title", "created_at")
            .order_by("-created_at")[:10]
        )
        return JsonResponse({"posts": posts})
# mysite/urls.py
from django.urls import path
from blog.views import PostListView

urlpatterns = [
    path("api/posts/", PostListView.as_view()),
]
curl -s http://127.0.0.1:8000/api/posts/

Output:

{"posts": [{"id": 1, "title": "Hello Django", "created_at": "2026-04-25T12:00:00Z"}]}

Essential management commands#

CommandPurpose
manage.py runserverStart dev server on 127.0.0.1:8000
manage.py makemigrationsGenerate migration files from model changes
manage.py migrateApply pending migrations to the database
manage.py createsuperuserCreate an admin user
manage.py shellInteractive Python shell with Django loaded
manage.py dbshellSQL shell for the configured database
manage.py collectstaticCopy static files to STATIC_ROOT for serving
manage.py testRun the test suite
manage.py checkValidate project configuration