Overview
Django 1.5, released on February 26, 2013, is a pivotal release for the framework. Its headline feature is the configurable user model via the AUTH_USER_MODEL setting, finally addressing one of the community's oldest requests. This release also brings experimental Python 3 support and streaming responses.
Key Features
Custom user model
The AUTH_USER_MODEL setting allows replacing the default User model with a fully custom one. You can use email as the primary identifier, add business-specific fields from the start, or tailor the model to the application's specific needs.
# settings.py
AUTH_USER_MODEL = 'accounts.CustomUser'
# accounts/models.py
from django.contrib.auth.models import AbstractBaseUser, BaseUserManager
from django.db import models
class CustomUserManager(BaseUserManager):
def create_user(self, email, password=None, **extra_fields):
if not email:
raise ValueError('An email address is required')
user = self.model(
email=self.normalize_email(email), **extra_fields
)
user.set_password(password)
user.save(using=self._db)
return user
class CustomUser(AbstractBaseUser):
email = models.EmailField(unique=True)
first_name = models.CharField(max_length=50)
last_name = models.CharField(max_length=50)
is_active = models.BooleanField(default=True)
objects = CustomUserManager()
USERNAME_FIELD = 'email'
def __str__(self):
return self.email
Streaming responses
The StreamingHttpResponse class allows sending an HTTP response in chunks, without loading the entire content into memory. This is especially useful for exporting large CSV files or generating bulky reports.
import csv
from django.http import StreamingHttpResponse
def generate_csv_rows(queryset):
"""Generate CSV rows one at a time."""
yield ['Name', 'Email', 'Joined']
for user in queryset.iterator():
yield [
user.last_name,
user.email,
user.date_joined.isoformat(),
]
class CSVBuffer:
"""Adapter for streaming CSV output."""
def write(self, value):
return value
def export_users(request):
queryset = CustomUser.objects.all()
writer = csv.writer(CSVBuffer())
rows = (writer.writerow(row) for row in generate_csv_rows(queryset))
response = StreamingHttpResponse(rows, content_type='text/csv')
response['Content-Disposition'] = 'attachment; filename="users.csv"'
return response
