Django Verification Loop
Run before PRs, after major changes, and pre-deploy to ensure Django application quality and security.
When to Activate
- Before opening a pull request for a Django project
- After major model changes, migration updates, or dependency upgrades
- Pre-deployment verification for staging or production
- Running full environment → lint → test → security → deploy readiness pipeline
- Validating migration safety and test coverage
Phase 1: Environment Check
bash1# Verify Python version 2python --version # Should match project requirements 3 4# Check virtual environment 5which python 6pip list --outdated 7 8# Verify environment variables 9python -c "import os; import environ; print('DJANGO_SECRET_KEY set' if os.environ.get('DJANGO_SECRET_KEY') else 'MISSING: DJANGO_SECRET_KEY')"
If environment is misconfigured, stop and fix.
Phase 2: Code Quality & Formatting
bash1# Type checking 2mypy . --config-file pyproject.toml 3 4# Linting with ruff 5ruff check . --fix 6 7# Formatting with black 8black . --check 9black . # Auto-fix 10 11# Import sorting 12isort . --check-only 13isort . # Auto-fix 14 15# Django-specific checks 16python manage.py check --deploy
Common issues:
- Missing type hints on public functions
- PEP 8 formatting violations
- Unsorted imports
- Debug settings left in production configuration
Phase 3: Migrations
bash1# Check for unapplied migrations 2python manage.py showmigrations 3 4# Create missing migrations 5python manage.py makemigrations --check 6 7# Dry-run migration application 8python manage.py migrate --plan 9 10# Apply migrations (test environment) 11python manage.py migrate 12 13# Check for migration conflicts 14python manage.py makemigrations --merge # Only if conflicts exist
Report:
- Number of pending migrations
- Any migration conflicts
- Model changes without migrations
Phase 4: Tests + Coverage
bash1# Run all tests with pytest 2pytest --cov=apps --cov-report=html --cov-report=term-missing --reuse-db 3 4# Run specific app tests 5pytest apps/users/tests/ 6 7# Run with markers 8pytest -m "not slow" # Skip slow tests 9pytest -m integration # Only integration tests 10 11# Coverage report 12open htmlcov/index.html
Report:
- Total tests: X passed, Y failed, Z skipped
- Overall coverage: XX%
- Per-app coverage breakdown
Coverage targets:
| Component | Target |
|---|---|
| Models | 90%+ |
| Serializers | 85%+ |
| Views | 80%+ |
| Services | 90%+ |
| Overall | 80%+ |
Phase 5: Security Scan
bash1# Dependency vulnerabilities 2pip-audit 3safety check --full-report 4 5# Django security checks 6python manage.py check --deploy 7 8# Bandit security linter 9bandit -r . -f json -o bandit-report.json 10 11# Secret scanning (if gitleaks is installed) 12gitleaks detect --source . --verbose 13 14# Environment variable check 15python -c "from django.core.exceptions import ImproperlyConfigured; from django.conf import settings; settings.DEBUG"
Report:
- Vulnerable dependencies found
- Security configuration issues
- Hardcoded secrets detected
- DEBUG mode status (should be False in production)
Phase 6: Django Management Commands
bash1# Check for model issues 2python manage.py check 3 4# Collect static files 5python manage.py collectstatic --noinput --clear 6 7# Create superuser (if needed for tests) 8echo "from apps.users.models import User; User.objects.create_superuser('admin@example.com', 'admin')" | python manage.py shell 9 10# Database integrity 11python manage.py check --database default 12 13# Cache verification (if using Redis) 14python -c "from django.core.cache import cache; cache.set('test', 'value', 10); print(cache.get('test'))"
Phase 7: Performance Checks
bash1# Django Debug Toolbar output (check for N+1 queries) 2# Run in dev mode with DEBUG=True and access a page 3# Look for duplicate queries in SQL panel 4 5# Query count analysis 6django-admin debugsqlshell # If django-debug-sqlshell installed 7 8# Check for missing indexes 9python manage.py shell << EOF 10from django.db import connection 11with connection.cursor() as cursor: 12 cursor.execute("SELECT table_name, index_name FROM information_schema.statistics WHERE table_schema = 'public'") 13 print(cursor.fetchall()) 14EOF
Report:
- Number of queries per page (should be < 50 for typical pages)
- Missing database indexes
- Duplicate queries detected
Phase 8: Static Assets
bash1# Check for npm dependencies (if using npm) 2npm audit 3npm audit fix 4 5# Build static files (if using webpack/vite) 6npm run build 7 8# Verify static files 9ls -la staticfiles/ 10python manage.py findstatic css/style.css
Phase 9: Configuration Review
python1# Run in Python shell to verify settings 2python manage.py shell << EOF 3from django.conf import settings 4import os 5 6# Critical checks 7checks = { 8 'DEBUG is False': not settings.DEBUG, 9 'SECRET_KEY set': bool(settings.SECRET_KEY and len(settings.SECRET_KEY) > 30), 10 'ALLOWED_HOSTS set': len(settings.ALLOWED_HOSTS) > 0, 11 'HTTPS enabled': getattr(settings, 'SECURE_SSL_REDIRECT', False), 12 'HSTS enabled': getattr(settings, 'SECURE_HSTS_SECONDS', 0) > 0, 13 'Database configured': settings.DATABASES['default']['ENGINE'] != 'django.db.backends.sqlite3', 14} 15 16for check, result in checks.items(): 17 status = '✓' if result else '✗' 18 print(f"{status} {check}") 19EOF
Phase 10: Logging Configuration
bash1# Test logging output 2python manage.py shell << EOF 3import logging 4logger = logging.getLogger('django') 5logger.warning('Test warning message') 6logger.error('Test error message') 7EOF 8 9# Check log files (if configured) 10tail -f /var/log/django/django.log
Phase 11: API Documentation (if DRF)
bash1# Generate schema 2python manage.py generateschema --format openapi-json > schema.json 3 4# Validate schema 5# Check if schema.json is valid JSON 6python -c "import json; json.load(open('schema.json'))" 7 8# Access Swagger UI (if using drf-yasg) 9# Visit http://localhost:8000/swagger/ in browser
Phase 12: Diff Review
bash1# Show diff statistics 2git diff --stat 3 4# Show actual changes 5git diff 6 7# Show changed files 8git diff --name-only 9 10# Check for common issues 11git diff | grep -i "todo\|fixme\|hack\|xxx" 12git diff | grep "print(" # Debug statements 13git diff | grep "DEBUG = True" # Debug mode 14git diff | grep "import pdb" # Debugger
Checklist:
- No debugging statements (print, pdb, breakpoint())
- No TODO/FIXME comments in critical code
- No hardcoded secrets or credentials
- Database migrations included for model changes
- Configuration changes documented
- Error handling present for external calls
- Transaction management where needed
Output Template
DJANGO VERIFICATION REPORT
==========================
Phase 1: Environment Check
✓ Python 3.11.5
✓ Virtual environment active
✓ All environment variables set
Phase 2: Code Quality
✓ mypy: No type errors
✗ ruff: 3 issues found (auto-fixed)
✓ black: No formatting issues
✓ isort: Imports properly sorted
✓ manage.py check: No issues
Phase 3: Migrations
✓ No unapplied migrations
✓ No migration conflicts
✓ All models have migrations
Phase 4: Tests + Coverage
Tests: 247 passed, 0 failed, 5 skipped
Coverage:
Overall: 87%
users: 92%
products: 89%
orders: 85%
payments: 91%
Phase 5: Security Scan
✗ pip-audit: 2 vulnerabilities found (fix required)
✓ safety check: No issues
✓ bandit: No security issues
✓ No secrets detected
✓ DEBUG = False
Phase 6: Django Commands
✓ collectstatic completed
✓ Database integrity OK
✓ Cache backend reachable
Phase 7: Performance
✓ No N+1 queries detected
✓ Database indexes configured
✓ Query count acceptable
Phase 8: Static Assets
✓ npm audit: No vulnerabilities
✓ Assets built successfully
✓ Static files collected
Phase 9: Configuration
✓ DEBUG = False
✓ SECRET_KEY configured
✓ ALLOWED_HOSTS set
✓ HTTPS enabled
✓ HSTS enabled
✓ Database configured
Phase 10: Logging
✓ Logging configured
✓ Log files writable
Phase 11: API Documentation
✓ Schema generated
✓ Swagger UI accessible
Phase 12: Diff Review
Files changed: 12
+450, -120 lines
✓ No debug statements
✓ No hardcoded secrets
✓ Migrations included
RECOMMENDATION: ⚠️ Fix pip-audit vulnerabilities before deploying
NEXT STEPS:
1. Update vulnerable dependencies
2. Re-run security scan
3. Deploy to staging for final testing
Pre-Deployment Checklist
- All tests passing
- Coverage ≥ 80%
- No security vulnerabilities
- No unapplied migrations
- DEBUG = False in production settings
- SECRET_KEY properly configured
- ALLOWED_HOSTS set correctly
- Database backups enabled
- Static files collected and served
- Logging configured and working
- Error monitoring (Sentry, etc.) configured
- CDN configured (if applicable)
- Redis/cache backend configured
- Celery workers running (if applicable)
- HTTPS/SSL configured
- Environment variables documented
Continuous Integration
GitHub Actions Example
yaml1# .github/workflows/django-verification.yml 2name: Django Verification 3 4on: [push, pull_request] 5 6jobs: 7 verify: 8 runs-on: ubuntu-latest 9 services: 10 postgres: 11 image: postgres:14 12 env: 13 POSTGRES_PASSWORD: postgres 14 options: >- 15 --health-cmd pg_isready 16 --health-interval 10s 17 --health-timeout 5s 18 --health-retries 5 19 20 steps: 21 - uses: actions/checkout@v3 22 23 - name: Set up Python 24 uses: actions/setup-python@v4 25 with: 26 python-version: '3.11' 27 28 - name: Cache pip 29 uses: actions/cache@v3 30 with: 31 path: ~/.cache/pip 32 key: ${{ runner.os }}-pip-${{ hashFiles('**/requirements.txt') }} 33 34 - name: Install dependencies 35 run: | 36 pip install -r requirements.txt 37 pip install ruff black mypy pytest pytest-django pytest-cov bandit safety pip-audit 38 39 - name: Code quality checks 40 run: | 41 ruff check . 42 black . --check 43 isort . --check-only 44 mypy . 45 46 - name: Security scan 47 run: | 48 bandit -r . -f json -o bandit-report.json 49 safety check --full-report 50 pip-audit 51 52 - name: Run tests 53 env: 54 DATABASE_URL: postgres://postgres:postgres@localhost:5432/test 55 DJANGO_SECRET_KEY: test-secret-key 56 run: | 57 pytest --cov=apps --cov-report=xml --cov-report=term-missing 58 59 - name: Upload coverage 60 uses: codecov/codecov-action@v3
Quick Reference
| Check | Command |
|---|---|
| Environment | python --version |
| Type checking | mypy . |
| Linting | ruff check . |
| Formatting | black . --check |
| Migrations | python manage.py makemigrations --check |
| Tests | pytest --cov=apps |
| Security | pip-audit && bandit -r . |
| Django check | python manage.py check --deploy |
| Collectstatic | python manage.py collectstatic --noinput |
| Diff stats | git diff --stat |
Remember: Automated verification catches common issues but doesn't replace manual code review and testing in staging environment.