
Django is a great framework, and adhering to best practices ensures maintainability, scalability, and overall code quality.
Table of Contents
Follow the DRY Principle (Don’t Repeat Yourself)
Use Django’s ORM Efficiently
Follow the ‘Fat Model, Thin View’ Principle
Separate Settings for Development and Production
Use Django’s Built-in Features
Implement Middleware Judiciously
Write Tests
Version Control with Git
Keep Dependencies Up-to-Date
Use Django’s Template System Wisely
Handle Static and Media Files
Secure Your Application
Document Your Code
Optimize Database Queries
Monitor and Optimize Performance
Conclusion
1. Follow the DRY Principle (Don’t Repeat Yourself)
Avoid duplicating code. If you find yourself repeating similar code in different places, refactor it into reusable functions, classes, or mixins.
Example: Instead of repeating a function across multiple views, create a utility function:
# utils.py
def send_welcome_email(user):
subject = "Welcome to Our Platform"
message = f"Hi {user.username}, welcome!"
user.email_user(subject, message)
# views.py
from .utils import send_welcome_email
def register_user(request):
user = User.objects.create(username="Aashish", email="aashish@example.com")
send_welcome_email(user)
return HttpResponse("User registered!")
2. Use Django’s ORM Efficiently
Django ORM is powerful, but inefficient queries can slow down performance.
Example: Use select_related()
to reduce database queries when fetching related objects.
# Inefficient: This will run an extra query for each book's author.
books = Book.objects.all()
for book in books:
print(book.author.name) # Triggers multiple queries
# Efficient: Uses join to fetch author details in a single query
books = Book.objects.select_related('author').all()
for book in books:
print(book.author.name) # Uses pre-fetched data, reducing queries
3. Follow the ‘Fat Model, Thin View’ Principle
Keep business logic inside models rather than views to make views cleaner.
Example:
# models.py
class Order(models.Model):
user = models.ForeignKey(User, on_delete=models.CASCADE)
total_price = models.DecimalField(max_digits=10, decimal_places=2)
def apply_discount(self, percentage):
self.total_price *= (1 - percentage / 100)
self.save()
# views.py
def apply_order_discount(request, order_id):
order = Order.objects.get(id=order_id)
order.apply_discount(10) # Apply 10% discount
return HttpResponse(f"New total: {order.total_price}")
4. Separate Settings for Development and Production
Use separate settings files to avoid accidental exposure of sensitive data.
Example:
settings/
├── __init__.py
├── base.py
├── development.py
├── production.py
In development.py
:
from .base import *
DEBUG = True
DATABASES = {"default": {"ENGINE": "django.db.backends.sqlite3", "NAME": "dev.db"}}
In production.py
:
from .base import *
DEBUG = False
DATABASES = {"default": {"ENGINE": "django.db.backends.postgresql", "NAME": "prod_db"}}
5. Use Django’s Built-in Features
Django provides many built-in tools that save development time.
Example: Instead of manually handling authentication, use Django’s authentication system:
from django.contrib.auth.decorators import login_required
@login_required
def profile(request):
return HttpResponse("Welcome to your profile")
6. Implement Middleware Judiciously
Use middleware for cross-cutting concerns but avoid unnecessary ones.
Example: Create a middleware to log request processing time.
import time
class LogExecutionTimeMiddleware:
def __init__(self, get_response):
self.get_response = get_response
def __call__(self, request):
start_time = time.time()
response = self.get_response(request)
execution_time = time.time() - start_time
print(f"Request took {execution_time:.2f} seconds")
return response
7. Write Tests
Django has a built-in testing framework to ensure code reliability.
Example:
from django.test import TestCase
from .models import Order
class OrderTestCase(TestCase):
def test_apply_discount(self):
order = Order.objects.create(total_price=100)
order.apply_discount(10)
self.assertEqual(order.total_price, 90)
8. Version Control with Git
Use Git for version control and maintain clean commit history.
Example Git workflow:
git checkout -b feature/add-login
# Make changes
git commit -m "Added login feature"
git push origin feature/add-login
9. Keep Dependencies Up-to-Date
Use pip freeze
to check outdated dependencies and update them.
pip freeze > requirements.txt
pip install --upgrade -r requirements.txt
10. Use Django’s Template System Wisely
Avoid placing complex logic in templates.
Example:
Instead of this in the template:
{% if user.is_staff and user.last_login and user.last_login.year == 2024 %}
<p>Welcome back, Admin!</p>
{% endif %}
Move logic to views.py
:
def admin_welcome_message(user):
return user.is_staff and user.last_login and user.last_login.year == 2024
And use it in the template:
{% if admin_welcome_message %}
<p>Welcome back, Admin!</p>
{% endif %}
11. Handle Static and Media Files
Configure Django to serve static and media files properly.
Example (Production - settings.py):
STATIC_URL = "/static/"
STATIC_ROOT = "/var/www/static/"
MEDIA_URL = "/media/"
MEDIA_ROOT = "/var/www/media/"
Use Amazon S3 for media storage in production:
DEFAULT_FILE_STORAGE = "storages.backends.s3boto3.S3Boto3Storage"
12. Secure Your Application
Enable Django’s security features.
Example:
SECURE_SSL_REDIRECT = True
CSRF_COOKIE_SECURE = True
SESSION_COOKIE_SECURE = True
13. Document Your Code
Write docstrings and comments to explain your code.
Example:
def calculate_total_price(price, discount):
"""
Calculate total price after applying discount.
:param price: Original price
:param discount: Discount percentage
:return: Final price after discount
"""
return price * (1 - discount / 100)
14. Optimize Database Queries
Use select_related()
and prefetch_related()
to minimize queries.
# Fetch authors and related books in a single query
authors = Author.objects.prefetch_related('books').all()
15. Monitor and Optimize Performance
Use Django Debug Toolbar to analyze performance.
pip install django-debug-toolbar
In settings.py
:
INSTALLED_APPS += ["debug_toolbar"]
MIDDLEWARE += ["debug_toolbar.middleware.DebugToolbarMiddleware"]
Conclusion
By following these best practices, you can build maintainable, scalable, and secure Django applications. Stay updated with Django’s latest releases and community recommendations to leverage new features and improvements.