Skip to main content
Course/Module 5/Topic 4 of 5Intermediate

security & Best Practices

Learn Django's built-in security features and best practices to protect your web applications from vulnerabilities.

55 minBy Priygop TeamLast updated: Feb 2026

Django security Features

Django includes many built-in security features to protect your applications from common web vulnerabilities. Understanding these features is essential for building secure applications.

security Best Practices

Example
# settings.py - security Settings
import os
from pathlib import Path

# security settings
SECRET_KEY = os.environ.get('SECRET_KEY', 'your-secret-key-here')

# HTTPS settings
SECURE_SSL_REDIRECT = True  # Redirect HTTP to HTTPS
SECURE_HSTS_SECONDS = 31536000  # 1 year
SECURE_HSTS_INCLUDE_SUBDOMAINS = True
SECURE_HSTS_PRELOAD = True

# Cookie settings
SESSION_COOKIE_SECURE = True  # Only send cookies over HTTPS
CSRF_COOKIE_SECURE = True
SESSION_COOKIE_HTTPONLY = True  # Prevent XSS
CSRF_COOKIE_HTTPONLY = True

# Content security Policy
CSP_DEFAULT_SRC = ("'self'",)
CSP_STYLE_SRC = ("'self'", "'unsafe-inline'")
CSP_SCRIPT_SRC = ("'self'",)

# CSRF Protection
CSRF_TRUSTED_ORIGINS = [
    'https://yourdomain.com',
    'https://www.yourdomain.com',
]

# XSS Protection
SECURE_BROWSER_XSS_FILTER = True
SECURE_CONTENT_TYPE_NOSNIFF = True

# Clickjacking Protection
X_FRAME_OPTIONS = 'DENY'

# SQL Injection Protection (Django ORM handles this automatically)
# Always use Django ORM instead of raw SQL when possible

# Example of secure form handling
from django.views.decorators.csrf import csrf_protect
from django.views.decorators.http import require_http_methods

@csrf_protect
@require_http_methods(["GET", "POST"])
def secure_form(request):
    if request.method == 'POST':
        form = MyForm(request.POST)
        if form.is_valid():
            # Process form data
            pass
    else:
        form = MyForm()
    
    return render(request, 'form.html', {'form': form})

# Rate limiting
from django.core.cache import cache
from django.http import HttpResponseTooManyRequests

def rate_limit(view_func):
    def wrapper(request, *args, **kwargs):
        # Get client IP
        client_ip = request.META.get('REMOTE_ADDR')
        
        # Check rate limit
        cache_key = f'rate_limit_{client_ip}'
        request_count = cache.get(cache_key, 0)
        
        if request_count > 100:  # 100 requests per hour
            return HttpResponseTooManyRequests('Rate limit exceeded')
        
        # Increment counter
        cache.set(cache_key, request_count + 1, 3600)  # 1 hour
        
        return view_func(request, *args, **kwargs)
    return wrapper

# Input validation
from django.core.validators import validate_email
from django.core.exceptions import ValidationError

def validate_user_input(data):
    errors = {}
    
    # Email validation
    try:
        validate_email(data.get('email', ''))
    except ValidationError:
        errors['email'] = 'Enter a valid email address.'
    
    # Password strength
    password = data.get('password', '')
    if len(password) < 8:
        errors['password'] = 'Password must be at least 8 characters long.'
    elif not any(c.isupper() for c in password):
        errors['password'] = 'Password must contain at least one uppercase letter.'
    elif not any(c.isdigit() for c in password):
        errors['password'] = 'Password must contain at least one number.'
    
    return errors

# File upload security
import os
from django.core.files.storage import default_storage

def secure_file_upload(file):
    # Check file size
    if file.size > 5 * 1024 * 1024:  # 5MB
        raise ValidationError('File size must be under 5MB.')
    
    # Check file extension
    allowed_extensions = ['.jpg', '.jpeg', '.png', '.gif', '.pdf']
    file_extension = os.path.splitext(file.name)[1].lower()
    
    if file_extension not in allowed_extensions:
        raise ValidationError('File type not allowed.')
    
    # Generate secure filename
    import uuid
    secure_filename = f"{uuid.uuid4()}{file_extension}"
    
    # Save file securely
    file_path = default_storage.save(f'uploads/{secure_filename}', file)
    return file_path

# SQL Injection Prevention
# ❌ Bad - Don't do this
def bad_query(request):
    user_input = request.GET.get('search', '')
    query = f"SELECT * FROM posts WHERE title LIKE '%{user_input}%'"
    # This is vulnerable to SQL injection

# ✅ Good - Use Django ORM
def good_query(request):
    user_input = request.GET.get('search', '')
    posts = Post.objects.filter(title__icontains=user_input)
    # Django ORM automatically escapes user input

# XSS Prevention
# Django templates automatically escape HTML
# {{ user_input }}  # Safe - automatically escaped
# {{ user_input|safe }}  # Dangerous - only use with trusted content

# CSRF Protection
# Django includes CSRF protection by default
# Include {% csrf_token %} in all forms

# Password hashing
from django.contrib.auth.hashers import make_password, check_password

# Hash password
hashed_password = make_password('my_password')

# Check password
is_valid = check_password('my_password', hashed_password)

Additional Resources

Recommended Reading

  • Django Forms Documentation
  • Django Authentication Documentation
  • Django security Best Practices

Online Resources

  • Django Form Validation
  • User Authentication Tutorial
  • security Best Practices Guide
Chat on WhatsApp
Priygop - Leading Professional Development Platform | Expert Courses & Interview Prep