The right tools can dramatically improve your Django development experience. This comprehensive guide covers essential tools, their configuration, and best practices for creating a productive development environment.
Why VS Code:
Essential Extensions:
{
"recommendations": [
"ms-python.python",
"ms-python.flake8",
"ms-python.black-formatter",
"ms-python.isort",
"batisteo.vscode-django",
"ms-python.debugpy",
"ms-vscode.vscode-json",
"redhat.vscode-yaml",
"ms-vscode.vscode-html-css-support",
"bradlc.vscode-tailwindcss"
]
}
VS Code Configuration:
// .vscode/settings.json
{
"python.defaultInterpreterPath": "./venv/bin/python",
"python.linting.enabled": true,
"python.linting.flake8Enabled": true,
"python.linting.pylintEnabled": false,
"python.formatting.provider": "black",
"python.formatting.blackArgs": ["--line-length=88"],
"python.sortImports.args": ["--profile", "black"],
"editor.formatOnSave": true,
"editor.codeActionsOnSave": {
"source.organizeImports": true
},
"files.associations": {
"*.html": "django-html",
"*.txt": "django-txt"
},
"emmet.includeLanguages": {
"django-html": "html"
},
"[python]": {
"editor.tabSize": 4,
"editor.insertSpaces": true,
"editor.rulers": [88]
},
"python.testing.pytestEnabled": true,
"python.testing.unittestEnabled": false,
"python.testing.pytestArgs": [
"."
]
}
Django Snippets:
// .vscode/django.code-snippets
{
"Django Model": {
"prefix": "djmodel",
"body": [
"class ${1:ModelName}(models.Model):",
" ${2:field_name} = models.${3:CharField}(max_length=${4:100})",
" created_at = models.DateTimeField(auto_now_add=True)",
" updated_at = models.DateTimeField(auto_now=True)",
"",
" class Meta:",
" verbose_name = '${5:Model Name}'",
" verbose_name_plural = '${6:Model Names}'",
"",
" def __str__(self):",
" return self.${7:field_name}"
]
},
"Django View": {
"prefix": "djview",
"body": [
"def ${1:view_name}(request):",
" ${2:# View logic here}",
" context = {",
" '${3:key}': ${4:value},",
" }",
" return render(request, '${5:template.html}', context)"
]
}
}
Why PyCharm:
Django Configuration:
# PyCharm Django Settings
# File → Settings → Languages & Frameworks → Django
# Enable Django Support: ✓
# Django project root: /path/to/your/project
# Settings: myproject/settings.py
# Manage script: manage.py
Useful PyCharm Features:
# Live templates for Django
# File → Settings → Editor → Live Templates → Django
# Model template
class $MODEL_NAME$(models.Model):
$FIELD_NAME$ = models.$FIELD_TYPE$($FIELD_ARGS$)
created_at = models.DateTimeField(auto_now_add=True)
def __str__(self):
return self.$RETURN_FIELD$
# View template
def $VIEW_NAME$(request$ARGS$):
$BODY$
return render(request, '$TEMPLATE$', $CONTEXT$)
Essential Plugins:
" .vimrc / init.vim
Plug 'davidhalter/jedi-vim' " Python autocompletion
Plug 'vim-python/python-syntax' " Python syntax highlighting
Plug 'psf/black', { 'branch': 'stable' } " Code formatting
Plug 'fisadev/vim-isort' " Import sorting
Plug 'w0rp/ale' " Linting
Plug 'tpope/vim-fugitive' " Git integration
Plug 'preservim/nerdtree' " File explorer
Plug 'junegunn/fzf.vim' " Fuzzy finder
" Django-specific
Plug 'tweekmonster/django-plus.vim' " Django enhancements
Plug 'mjbrownie/django-template-textobjects' " Template objects
Installation:
# macOS
brew install postgresql
brew services start postgresql
# Ubuntu/Debian
sudo apt-get install postgresql postgresql-contrib
sudo systemctl start postgresql
# Create database and user
sudo -u postgres psql
CREATE DATABASE django_dev;
CREATE USER django_user WITH PASSWORD 'secure_password';
GRANT ALL PRIVILEGES ON DATABASE django_dev TO django_user;
pgAdmin Configuration:
# Django settings for PostgreSQL
DATABASES = {
'default': {
'ENGINE': 'django.db.backends.postgresql',
'NAME': 'django_dev',
'USER': 'django_user',
'PASSWORD': 'secure_password',
'HOST': 'localhost',
'PORT': '5432',
'OPTIONS': {
'init_command': "SET sql_mode='STRICT_TRANS_TABLES'",
},
}
}
DBeaver (Cross-platform):
-- Connection settings
Host: localhost
Port: 5432
Database: django_dev
Username: django_user
Password: secure_password
-- Useful queries for Django development
SELECT * FROM django_migrations ORDER BY applied DESC LIMIT 10;
SELECT * FROM auth_user WHERE is_superuser = true;
SELECT table_name FROM information_schema.tables WHERE table_schema = 'public';
TablePlus (macOS/Windows):
Global Git Setup:
# Basic configuration
git config --global user.name "Your Name"
git config --global user.email "your.email@example.com"
git config --global init.defaultBranch main
# Useful aliases
git config --global alias.co checkout
git config --global alias.br branch
git config --global alias.ci commit
git config --global alias.st status
git config --global alias.unstage 'reset HEAD --'
git config --global alias.last 'log -1 HEAD'
git config --global alias.visual '!gitk'
# Better diff and merge tools
git config --global diff.tool vimdiff
git config --global merge.tool vimdiff
Project-specific .gitignore:
# Django
*.log
*.pot
*.pyc
__pycache__/
local_settings.py
db.sqlite3
db.sqlite3-journal
media/
# Virtual Environment
venv/
env/
ENV/
# IDE
.vscode/
.idea/
*.swp
*.swo
*~
# OS
.DS_Store
.DS_Store?
._*
.Spotlight-V100
.Trashes
ehthumbs.db
Thumbs.db
# Environment variables
.env
.env.local
.env.*.local
# Static files
staticfiles/
static_collected/
# Node modules (if using frontend tools)
node_modules/
npm-debug.log*
# Coverage reports
htmlcov/
.coverage
.coverage.*
coverage.xml
*.cover
.hypothesis/
.pytest_cache/
Installation and Setup:
# Install pre-commit
pip install pre-commit
# Create .pre-commit-config.yaml
cat > .pre-commit-config.yaml << EOF
repos:
- repo: https://github.com/pre-commit/pre-commit-hooks
rev: v4.4.0
hooks:
- id: trailing-whitespace
- id: end-of-file-fixer
- id: check-yaml
- id: check-added-large-files
- id: check-merge-conflict
- repo: https://github.com/psf/black
rev: 23.9.1
hooks:
- id: black
language_version: python3
- repo: https://github.com/pycqa/isort
rev: 5.12.0
hooks:
- id: isort
args: ["--profile", "black"]
- repo: https://github.com/pycqa/flake8
rev: 6.1.0
hooks:
- id: flake8
args: [--max-line-length=88, --extend-ignore=E203]
- repo: https://github.com/pycqa/bandit
rev: 1.7.5
hooks:
- id: bandit
args: ["-r", ".", "-x", "tests/"]
EOF
# Install the hooks
pre-commit install
Black (Code Formatter):
# pyproject.toml
[tool.black]
line-length = 88
target-version = ['py38', 'py39', 'py310', 'py311']
include = '\.pyi?$'
extend-exclude = '''
/(
# directories
\.eggs
| \.git
| \.hg
| \.mypy_cache
| \.tox
| \.venv
| build
| dist
| migrations
)/
'''
isort (Import Sorting):
# pyproject.toml
[tool.isort]
profile = "black"
multi_line_output = 3
line_length = 88
known_django = "django"
known_first_party = "myproject"
sections = ["FUTURE", "STDLIB", "DJANGO", "THIRDPARTY", "FIRSTPARTY", "LOCALFOLDER"]
Flake8 (Linting):
# setup.cfg or .flake8
[flake8]
max-line-length = 88
extend-ignore = E203, E266, E501, W503
max-complexity = 10
select = B,C,E,F,W,T4,B9
exclude =
.git,
__pycache__,
migrations,
.venv,
build,
dist
Ruff (Fast Linter):
# pyproject.toml
[tool.ruff]
line-length = 88
target-version = "py38"
select = [
"E", # pycodestyle errors
"W", # pycodestyle warnings
"F", # pyflakes
"I", # isort
"B", # flake8-bugbear
"C4", # flake8-comprehensions
"UP", # pyupgrade
]
ignore = [
"E501", # line too long, handled by black
"B008", # do not perform function calls in argument defaults
]
exclude = [
".git",
"__pycache__",
"migrations",
".venv",
]
[tool.ruff.per-file-ignores]
"__init__.py" = ["F401"]
mypy Configuration:
# pyproject.toml
[tool.mypy]
python_version = "3.8"
check_untyped_defs = true
ignore_missing_imports = true
warn_unused_ignores = true
warn_redundant_casts = true
warn_unused_configs = true
plugins = ["mypy_django_plugin.main"]
[tool.django-stubs]
django_settings_module = "myproject.settings"
[[tool.mypy.overrides]]
module = "*.migrations.*"
ignore_errors = true
Installation:
pip install pytest pytest-django pytest-cov factory-boy
Configuration:
# pyproject.toml
[tool.pytest.ini_options]
DJANGO_SETTINGS_MODULE = "myproject.settings.testing"
python_files = ["tests.py", "test_*.py", "*_tests.py"]
addopts = [
"--cov=myproject",
"--cov-report=html",
"--cov-report=term-missing",
"--cov-fail-under=80",
"--strict-markers",
"--strict-config",
"--disable-warnings",
]
testpaths = ["tests"]
markers = [
"slow: marks tests as slow (deselect with '-m \"not slow\"')",
"integration: marks tests as integration tests",
"unit: marks tests as unit tests",
]
Factory Boy Setup:
# tests/factories.py
import factory
from django.contrib.auth.models import User
from myapp.models import Post
class UserFactory(factory.django.DjangoModelFactory):
class Meta:
model = User
username = factory.Sequence(lambda n: f"user{n}")
email = factory.LazyAttribute(lambda obj: f"{obj.username}@example.com")
first_name = factory.Faker("first_name")
last_name = factory.Faker("last_name")
class PostFactory(factory.django.DjangoModelFactory):
class Meta:
model = Post
title = factory.Faker("sentence", nb_words=4)
content = factory.Faker("text")
author = factory.SubFactory(UserFactory)
published = True
Installation and Setup:
pip install django-debug-toolbar
# settings/development.py
INSTALLED_APPS += ['debug_toolbar']
MIDDLEWARE += ['debug_toolbar.middleware.DebugToolbarMiddleware']
DEBUG_TOOLBAR_CONFIG = {
'SHOW_TOOLBAR_CALLBACK': lambda request: True,
'SHOW_COLLAPSED': True,
}
# urls.py
if settings.DEBUG:
import debug_toolbar
urlpatterns = [
path('__debug__/', include(debug_toolbar.urls)),
] + urlpatterns
Installation:
pip install django-extensions
Useful Commands:
# Enhanced shell with IPython
python manage.py shell_plus
# Generate model graphs
python manage.py graph_models -a -o models.png
# Show URLs
python manage.py show_urls
# Validate templates
python manage.py validate_templates
# Clear cache
python manage.py clear_cache
# Reset database
python manage.py reset_db
Installation:
pip install django-silk
Configuration:
# settings/development.py
INSTALLED_APPS += ['silk']
MIDDLEWARE += ['silk.middleware.SilkyMiddleware']
# urls.py
urlpatterns += [path('silk/', include('silk.urls', namespace='silk'))]
# Optional: Silk configuration
SILKY_PYTHON_PROFILER = True
SILKY_PYTHON_PROFILER_BINARY = True
SILKY_AUTHENTICATION = True
SILKY_AUTHORISATION = True
memory_profiler:
pip install memory-profiler psutil
# Usage
@profile
def my_view(request):
# Your view code here
pass
# Run with profiling
python -m memory_profiler manage.py runserver
Installation and Usage:
pip install pip-tools
# Create requirements.in
echo "Django>=4.2,<5.0" > requirements.in
echo "psycopg2-binary" >> requirements.in
# Generate locked requirements
pip-compile requirements.in
# Install dependencies
pip-sync requirements.txt
# Upgrade packages
pip-compile --upgrade requirements.in
Installation:
curl -sSL https://install.python-poetry.org | python3 -
# Initialize project
poetry init
# Add dependencies
poetry add django psycopg2-binary
# Add development dependencies
poetry add --group dev pytest black flake8
# Install dependencies
poetry install
# Activate virtual environment
poetry shell
FROM python:3.11-slim
WORKDIR /app
# Install system dependencies
RUN apt-get update && apt-get install -y \
postgresql-client \
build-essential \
&& rm -rf /var/lib/apt/lists/*
# Install Python dependencies
COPY requirements.txt .
RUN pip install --no-cache-dir -r requirements.txt
# Copy project
COPY . .
# Create non-root user
RUN useradd --create-home --shell /bin/bash django
USER django
EXPOSE 8000
CMD ["python", "manage.py", "runserver", "0.0.0.0:8000"]
version: '3.8'
services:
web:
build: .
ports:
- "8000:8000"
volumes:
- .:/app
environment:
- DEBUG=1
- DATABASE_URL=postgresql://django:password@db:5432/django_dev
depends_on:
- db
- redis
command: python manage.py runserver 0.0.0.0:8000
db:
image: postgres:15
environment:
POSTGRES_DB: django_dev
POSTGRES_USER: django
POSTGRES_PASSWORD: password
volumes:
- postgres_data:/var/lib/postgresql/data
ports:
- "5432:5432"
redis:
image: redis:7-alpine
ports:
- "6379:6379"
volumes:
postgres_data:
# Makefile
.PHONY: help install test lint format clean migrate shell
help:
@echo "Available commands:"
@echo " install Install dependencies"
@echo " test Run tests"
@echo " lint Run linting"
@echo " format Format code"
@echo " migrate Run migrations"
@echo " shell Open Django shell"
install:
pip install -r requirements.txt
test:
pytest
lint:
flake8 .
mypy .
format:
black .
isort .
clean:
find . -type f -name "*.pyc" -delete
find . -type d -name "__pycache__" -delete
migrate:
python manage.py makemigrations
python manage.py migrate
shell:
python manage.py shell_plus
runserver:
python manage.py runserver
collectstatic:
python manage.py collectstatic --noinput
requirements:
pip-compile requirements.in
pip-compile requirements-dev.in
This comprehensive tooling setup provides a solid foundation for professional Django development, ensuring code quality, productivity, and maintainability across your projects.
Development Environment
A well-configured development environment is crucial for productive Django development. This section covers everything you need to set up a professional, efficient, and maintainable development workflow that scales from personal projects to enterprise applications.
Virtual Environments
Virtual environments are essential for Python and Django development, providing isolated spaces for project dependencies. This comprehensive guide covers everything you need to know about creating, managing, and optimizing virtual environments for Django projects.