Last updated: April 2026 · AnomixLabs Engineering Team
Decisions made in the early hours of a Django project directly impact months of development. Starting correctly is always cheaper than rewriting later.
1. Why Django 5.2 LTS?
Django 5.2 is the Long-Term Support (LTS) release, published in April 2025, and will receive security updates until 2028. Always prefer an LTS version for production projects — work on a stable foundation instead of waiting for your dependent packages to adapt to every major Django release.
Highlights of Django 5.2: Composite primary key support, LoginRequiredMiddleware (enforce login for all views in a single line), ASGI performance improvements, and an enhanced AsyncClient.
2. Installation: uv (Recommended) or pip
uv is a Python package manager written in Rust, 10-100x faster than pip. It has become the standard tool in the Python ecosystem for 2024-2025:
# Option A: uv (recommended)
$ pip install uv
$ uv venv .venv
$ source .venv/bin/activate # Windows: .venv\Scripts\activate
$ uv pip install django==5.2
# Option B: classic pip
$ python -m venv .venv
$ source .venv/bin/activate
$ pip install django==5.2
# Create project
$ django-admin startproject config .
$ python manage.py startapp accounts
3. Custom User Model — The First and Most Critical Step
Django's most important best practice: define a custom user model before the first migration. Doing it later means migration hell — existing auth tables, foreign key relationships, and the permission structure will be completely broken. In our experience, every project that made this mistake faced significant refactoring costs:
from django.contrib.auth.models import AbstractUser
from django.db import models
class User(AbstractUser):
# Just 2 fields for now — easily expandable later
phone = models.CharField(max_length=20, blank=True)
avatar = models.ImageField(upload_to='avatars/', blank=True)
class Meta:
verbose_name = 'User'
verbose_name_plural = 'Users'
AUTH_USER_MODEL = 'accounts.User'
4. .env Management with django-environ
Never hardcode sensitive information like SECRET_KEY, database passwords, or API keys into your source code. django-environ reads this information from a .env file:
$ pip install django-environ
SECRET_KEY=django-insecure-change-this
DEBUG=True
ALLOWED_HOSTS=localhost,127.0.0.1
DATABASE_URL=postgres://user:pass@localhost:5432/mydb
EMAIL_HOST_USER=example@gmail.com
EMAIL_HOST_PASSWORD=app-password
import environ
env = environ.Env(DEBUG=(bool, False))
environ.Env.read_env(BASE_DIR / '.env')
SECRET_KEY = env('SECRET_KEY')
DEBUG = env('DEBUG')
ALLOWED_HOSTS = env.list('ALLOWED_HOSTS', default=['*'])
DATABASES = {'default': env.db()}
5. Recommended Directory Structure
myproject/
├── config/ # settings, urls, wsgi, asgi
│ ├── settings.py
│ ├── urls.py
│ └── wsgi.py
├── apps/
│ ├── accounts/ # Custom User model — first app
│ ├── blog/
│ │ ├── models/
│ │ │ ├── __init__.py
│ │ │ └── article.py
│ │ ├── views/
│ │ └── tests/
│ └── core/ # Common utilities
├── static/
├── media/
├── templates/
├── locale/
├── .env
├── .gitignore
└── manage.py
6. Full settings.py Organization
# ── CORE ────────────────────────────────────────
SECRET_KEY = env('SECRET_KEY')
DEBUG = env('DEBUG')
ALLOWED_HOSTS = env.list('ALLOWED_HOSTS')
# ── APPS ────────────────────────────────────────
INSTALLED_APPS = [
'django.contrib.admin',
'django.contrib.auth',
'apps.accounts',
'apps.blog',
]
# ── DATABASE ─────────────────────────────────────
DATABASES = {'default': env.db()}
# ── AUTH ─────────────────────────────────────────
AUTH_USER_MODEL = 'accounts.User'
# ── STATIC & MEDIA ───────────────────────────────
STATIC_URL = '/static/'
STATICFILES_DIRS = [BASE_DIR / 'static']
STATIC_ROOT = BASE_DIR / 'staticfiles'
MEDIA_URL = '/media/'
MEDIA_ROOT = BASE_DIR / 'media'
# ── EMAIL ────────────────────────────────────────
EMAIL_BACKEND = 'django.core.mail.backends.console.EmailBackend'
7. PostgreSQL Setup
# Ubuntu/Debian
$ sudo apt install postgresql postgresql-contrib libpq-dev
$ sudo -u postgres psql
CREATE DATABASE mydb;
CREATE USER myuser WITH PASSWORD 'mypassword';
GRANT ALL PRIVILEGES ON DATABASE mydb TO myuser;
\q
# Python connection
$ pip install psycopg2-binary
# Initial migration
$ python manage.py migrate
8. Pre-Commit Hooks
Tools that automatically check code quality before every commit. With ruff (linter + formatter) and mypy (type checking):
$ pip install pre-commit ruff mypy
$ pre-commit install
repos:
- repo: https://github.com/astral-sh/ruff-pre-commit
rev: v0.3.0
hooks:
- id: ruff
args: [--fix]
- id: ruff-format
- repo: https://github.com/pre-commit/pre-commit-hooks
rev: v4.5.0
hooks:
- id: trailing-whitespace
- id: end-of-file-fixer
- id: check-merge-conflict
- id: check-env-vars
args: [--no-empty-required]
9. Security Checklist
# Django's built-in security check
$ python manage.py check --deploy
# Typical output:
# WARNINGS:
# ?: (security.W004) You have not set SECURE_HSTS_SECONDS...
# ?: (security.W008) SECURE_SSL_REDIRECT setting is not set...
# HTTPS security settings (when DEBUG=False)
SECURE_SSL_REDIRECT = True
SECURE_HSTS_SECONDS = 31536000 # 1 year
SECURE_HSTS_INCLUDE_SUBDOMAINS = True
SECURE_HSTS_PRELOAD = True
SESSION_COOKIE_SECURE = True
CSRF_COOKIE_SECURE = True
SECURE_CONTENT_TYPE_NOSNIFF = True
10. Staging / Production Environment Separation
Using environment-specific files instead of a single settings.py provides flexibility for large projects:
config/
├── settings/
│ ├── __init__.py
│ ├── base.py # Common settings
│ ├── local.py # Development (DEBUG=True, SQLite)
│ ├── staging.py # Test server
│ └── production.py # Live (DEBUG=False, PostgreSQL)
# Switch via environment variable
DJANGO_SETTINGS_MODULE=config.settings.production python manage.py migrate
# In .env file
DJANGO_SETTINGS_MODULE=config.settings.local
Summary
The sequence for setting up a Django 5.2 LTS project: AbstractUser (before the first migration), django-environ (.env management), modular settings (base/local/production), PostgreSQL (production standard), pre-commit (code quality), security checklist (python manage.py check --deploy). These 6 steps form the healthy foundation of your project.
Frequently Questions
Should I use AbstractUser or AbstractBaseUser? expand_more
What's the difference between uv and pip? expand_more
How do I migrate from SQLite to PostgreSQL? expand_more
How do I securely generate a SECRET_KEY? expand_more
Should I use pyproject.toml or requirements.txt? expand_more
Django 5.2 vs 4.2 LTS: Should I upgrade? expand_more
What is LoginRequiredMiddleware and what does it do? expand_more
Ali Kasımoğlu
Full-stack Developer & Founder of AnomixLabs
A software developer specializing in the Python and Django ecosystem. Focuses on modern web architectures, AI integrations, and minimalist user experiences. Under the AnomixLabs umbrella, he aims to transform complex problems into lean and effective digital solutions.