10 Python Tricks Every Django Developer Should Know
# Python Tricks for Django Developers
Even experienced Django developers might not know all of Python's powerful features. Here are 10 tricks that will improve your code.
## 1. F-Strings with Expressions
Go beyond simple variable insertion:
```python
# Formatting numbers
price = 49.99
print(f"Price: ${price:.2f}") # Price: $49.99
# Debug mode (Python 3.8+)
user = "john"
print(f"{user=}") # user='john'
# Expressions
items = [1, 2, 3]
print(f"Total: {sum(items)}") # Total: 6
```
## 2. Walrus Operator (:=)
Assign and use in one expression:
```python
# Without walrus
data = expensive_function()
if data:
process(data)
# With walrus
if data := expensive_function():
process(data)
# Great for Django querysets
if users := User.objects.filter(is_active=True):
send_newsletter(users)
```
## 3. Dict Merge Operator
Python 3.9+ makes dict merging elegant:
```python
defaults = {'page': 1, 'per_page': 20}
user_prefs = {'per_page': 50}
# Merge dicts
settings = defaults | user_prefs
# {'page': 1, 'per_page': 50}
# In-place merge
defaults |= user_prefs
```
## 4. Structural Pattern Matching
Python 3.10+ brings powerful matching:
```python
def handle_request(request):
match request.method:
case 'GET':
return list_items()
case 'POST':
return create_item(request.data)
case 'PUT' | 'PATCH':
return update_item(request.data)
case _:
return method_not_allowed()
```
## 5. Dataclasses for DTOs
Replace boilerplate with dataclasses:
```python
from dataclasses import dataclass, field
from typing import Optional
@dataclass
class ProductDTO:
name: str
price: float
description: str = ""
tags: list = field(default_factory=list)
@property
def price_with_tax(self):
return self.price * 1.21
product = ProductDTO("Widget", 29.99)
print(product.price_with_tax) # 36.29
```
## 6. Context Managers for Resource Management
Clean up resources automatically:
```python
from contextlib import contextmanager
@contextmanager
def temporary_setting(key, value):
from django.conf import settings
original = getattr(settings, key)
setattr(settings, key, value)
try:
yield
finally:
setattr(settings, key, original)
# Usage
with temporary_setting('DEBUG', True):
# DEBUG is True here
run_tests()
# DEBUG is back to original
```
## 7. Generators for Memory Efficiency
Process large datasets without loading everything:
```python
def process_large_queryset(queryset, batch_size=1000):
"""Yield items in batches to save memory."""
total = queryset.count()
for start in range(0, total, batch_size):
for item in queryset[start:start + batch_size]:
yield item
# Process millions of records efficiently
for user in process_large_queryset(User.objects.all()):
send_email(user)
```
## 8. Functools for Caching
Cache expensive function results:
```python
from functools import lru_cache, cache
@lru_cache(maxsize=128)
def get_user_permissions(user_id):
user = User.objects.get(id=user_id)
return list(user.get_all_permissions())
# Python 3.9+ unlimited cache
@cache
def get_site_settings():
return SiteSettings.objects.first()
```
## 9. Type Hints for Better Code
Make your code self-documenting:
```python
from typing import Optional, List
from django.db.models import QuerySet
def get_active_products(
category: Optional[str] = None,
limit: int = 10
) -> QuerySet['Product']:
"""Get active products, optionally filtered by category."""
qs = Product.objects.filter(is_active=True)
if category:
qs = qs.filter(category__slug=category)
return qs[:limit]
```
## 10. Unpacking Operators
Powerful argument passing:
```python
# Unpack lists/tuples
def create_user(username, email, password):
pass
user_data = ['john', 'john@example.com', 'secret']
create_user(*user_data)
# Unpack dicts
config = {'username': 'john', 'email': 'john@example.com'}
create_user(**config, password='secret')
# Combine multiple dicts
full_config = {**defaults, **user_config, **overrides}
```
## Bonus: Django-Specific Tricks
### Query Optimization with select_related
```python
# Bad: N+1 queries
for order in Order.objects.all():
print(order.user.email) # Query each time
# Good: Single query with JOIN
for order in Order.objects.select_related('user'):
print(order.user.email) # No extra query
```
### Bulk Operations
```python
# Create many objects efficiently
Product.objects.bulk_create([
Product(name=f"Product {i}", price=9.99)
for i in range(1000)
])
# Update many objects
Product.objects.filter(category='old').update(category='new')
```
## Conclusion
These Python features can make your Django code more readable, efficient, and maintainable. Start incorporating them into your projects today!
What's your favorite Python trick? Share in the comments!