Skip to main content

Django Registration

Introduction

User registration is a fundamental feature of most web applications. It allows users to create accounts, access personalized features, and maintain their profiles. Django, being a comprehensive web framework, provides robust tools for implementing user registration systems.

In this tutorial, we'll learn how to build a complete registration system in Django that allows users to:

  • Create new accounts
  • Receive verification emails
  • Verify their email addresses
  • Log in to their newly created accounts

By the end of this guide, you'll understand the core concepts of user registration in Django and be able to implement a secure registration system in your own applications.

Prerequisites

Before we begin, make sure you have:

  • Basic knowledge of Django models, views, and templates
  • A Django project already set up
  • Understanding of basic HTML and forms

Setting Up User Registration

Step 1: Configure the User Model

Django comes with a built-in User model that handles authentication. For most applications, this model provides everything needed for registration and authentication. Let's start by ensuring our settings are properly configured.

In your settings.py file, make sure you have the authentication apps included:

python
INSTALLED_APPS = [
# Django built-in apps
'django.contrib.admin',
'django.contrib.auth',
'django.contrib.contenttypes',
'django.contrib.sessions',
'django.contrib.messages',
'django.contrib.staticfiles',

# Your apps
'your_app_name',
]

Step 2: Create a Registration Form

We need a form to collect user information. Django provides a UserCreationForm that we can extend for our needs:

python
# forms.py
from django import forms
from django.contrib.auth.forms import UserCreationForm
from django.contrib.auth.models import User

class RegistrationForm(UserCreationForm):
email = forms.EmailField(required=True)

class Meta:
model = User
fields = ("username", "email", "password1", "password2")

def save(self, commit=True):
user = super().save(commit=False)
user.email = self.cleaned_data["email"]
if commit:
user.save()
return user

This form extends Django's built-in UserCreationForm to include an email field, which isn't required by default.

Step 3: Create Registration Views

Next, we'll create views to handle the registration process:

python
# views.py
from django.shortcuts import render, redirect
from django.contrib.auth import login, authenticate
from .forms import RegistrationForm
from django.contrib.sites.shortcuts import get_current_site
from django.template.loader import render_to_string
from django.utils.http import urlsafe_base64_encode, urlsafe_base64_decode
from django.utils.encoding import force_bytes, force_str
from django.core.mail import EmailMessage
from .tokens import account_activation_token
from django.contrib.auth.models import User

def register(request):
if request.method == 'POST':
form = RegistrationForm(request.POST)
if form.is_valid():
user = form.save(commit=False)
user.is_active = False # Deactivate account till it is confirmed
user.save()

# Send an email to the user with the token:
current_site = get_current_site(request)
mail_subject = 'Activate your account.'
message = render_to_string('registration/account_activation_email.html', {
'user': user,
'domain': current_site.domain,
'uid': urlsafe_base64_encode(force_bytes(user.pk)),
'token': account_activation_token.make_token(user),
})
to_email = form.cleaned_data.get('email')
email = EmailMessage(
mail_subject, message, to=[to_email]
)
email.send()

return render(request, 'registration/register_confirm.html')
else:
form = RegistrationForm()
return render(request, 'registration/register.html', {'form': form})

def activate(request, uidb64, token):
try:
uid = force_str(urlsafe_base64_decode(uidb64))
user = User.objects.get(pk=uid)
except(TypeError, ValueError, OverflowError, User.DoesNotExist):
user = None

if user is not None and account_activation_token.check_token(user, token):
user.is_active = True
user.save()
login(request, user)
return render(request, 'registration/activation_successful.html')
else:
return render(request, 'registration/activation_invalid.html')

Step 4: Create a Token Generator

Create a new file called tokens.py for the account activation token:

python
# tokens.py
from django.contrib.auth.tokens import PasswordResetTokenGenerator

class TokenGenerator(PasswordResetTokenGenerator):
def _make_hash_value(self, user, timestamp):
return (
str(user.pk) + str(timestamp) + str(user.is_active)
)

account_activation_token = TokenGenerator()

This token generator creates unique tokens for email verification.

Step 5: Create Templates for Registration

Now let's create the necessary templates:

register.html

html
{% extends 'base.html' %}

{% block content %}
<div class="registration-form">
<h2>Register</h2>
<form method="post">
{% csrf_token %}
<div class="form-group">
{{ form.as_p }}
</div>
<button type="submit" class="btn btn-primary">Register</button>
</form>
<p>Already have an account? <a href="{% url 'login' %}">Login</a></p>
</div>
{% endblock %}

register_confirm.html

html
{% extends 'base.html' %}

{% block content %}
<div class="register-confirm">
<h2>Account Registration</h2>
<p>
We have sent an email with instructions to activate your account.
Please check your inbox and follow the instructions to complete registration.
</p>
</div>
{% endblock %}

account_activation_email.html

html
{% autoescape off %}
Hi {{ user.username }},

Please click on the link below to confirm your registration:

http://{{ domain }}{% url 'activate' uidb64=uid token=token %}

If you did not make this request, you can simply ignore this email.

{% endautoescape %}

activation_successful.html

html
{% extends 'base.html' %}

{% block content %}
<div class="activation-successful">
<h2>Account Activated!</h2>
<p>
Your account has been successfully activated! You are now logged in.
</p>
<a href="{% url 'home' %}" class="btn btn-primary">Go to Homepage</a>
</div>
{% endblock %}

activation_invalid.html

html
{% extends 'base.html' %}

{% block content %}
<div class="activation-invalid">
<h2>Activation Failed</h2>
<p>
The activation link is invalid or has expired.
Please try registering again or contact support if you need assistance.
</p>
<a href="{% url 'register' %}" class="btn btn-primary">Register Again</a>
</div>
{% endblock %}

Step 6: Set Up URLs

Let's configure our URLs:

python
# urls.py
from django.urls import path
from . import views

urlpatterns = [
path('register/', views.register, name='register'),
path('activate/<uidb64>/<token>/', views.activate, name='activate'),
]

Step 7: Configure Email Settings

To make email sending work, configure your email settings in settings.py:

python
# For development (prints emails to console)
EMAIL_BACKEND = 'django.core.mail.backends.console.EmailBackend'

# For production (example with Gmail)
"""
EMAIL_BACKEND = 'django.core.mail.backends.smtp.EmailBackend'
EMAIL_HOST = 'smtp.gmail.com'
EMAIL_PORT = 587
EMAIL_USE_TLS = True
EMAIL_HOST_USER = '[email protected]'
EMAIL_HOST_PASSWORD = 'your-password-or-app-password'
"""

Creating a Simple Registration Without Email Verification

For simpler applications, you might want to implement registration without email verification. Here's how:

python
# views.py - simplified version
def register_simple(request):
if request.method == 'POST':
form = RegistrationForm(request.POST)
if form.is_valid():
user = form.save()
# Log the user in immediately after registration
username = form.cleaned_data.get('username')
raw_password = form.cleaned_data.get('password1')
user = authenticate(username=username, password=raw_password)
login(request, user)
return redirect('home') # Redirect to home page
else:
form = RegistrationForm()
return render(request, 'registration/register.html', {'form': form})

Customizing the User Model

Django's built-in User model might not always fit your needs. If you need additional fields for registration, it's best to use a custom user model or create a profile model:

Option 1: User Profile Model

python
# models.py
from django.db import models
from django.contrib.auth.models import User
from django.db.models.signals import post_save
from django.dispatch import receiver

class Profile(models.Model):
user = models.OneToOneField(User, on_delete=models.CASCADE)
bio = models.TextField(max_length=500, blank=True)
location = models.CharField(max_length=30, blank=True)
birth_date = models.DateField(null=True, blank=True)

def __str__(self):
return self.user.username

@receiver(post_save, sender=User)
def create_user_profile(sender, instance, created, **kwargs):
if created:
Profile.objects.create(user=instance)

@receiver(post_save, sender=User)
def save_user_profile(sender, instance, **kwargs):
instance.profile.save()

First, create a custom user model:

python
# models.py
from django.db import models
from django.contrib.auth.models import AbstractUser

class CustomUser(AbstractUser):
bio = models.TextField(max_length=500, blank=True)
location = models.CharField(max_length=30, blank=True)
birth_date = models.DateField(null=True, blank=True)

Then, in your settings.py, specify the custom user model:

python
AUTH_USER_MODEL = 'your_app_name.CustomUser'

And create a registration form for this custom user:

python
# forms.py
from django import forms
from django.contrib.auth.forms import UserCreationForm
from .models import CustomUser

class CustomUserCreationForm(UserCreationForm):
class Meta:
model = CustomUser
fields = ('username', 'email', 'birth_date', 'password1', 'password2')

Security Best Practices

When implementing registration, consider these security best practices:

  1. Password Validation: Django's UserCreationForm includes strong password validation by default
  2. HTTPS: Always use HTTPS for registration/login forms
  3. CSRF Protection: Django includes CSRF protection by default; ensure it's not disabled
  4. Rate Limiting: Implement rate limiting for registration attempts
  5. Captcha: Consider adding captcha for registration to prevent spam
  6. Email Verification: Verify user emails before activating accounts

Here's how to implement a simple rate limiter:

python
# views.py with rate limiting
from django.core.cache import cache
from django.http import HttpResponse

def register_with_rate_limit(request):
# Get client IP
client_ip = get_client_ip(request)
# Check if IP is rate limited
if cache.get(f"registration_limit_{client_ip}"):
return HttpResponse("Too many registration attempts. Please try again later.", status=429)

if request.method == 'POST':
# Process form
# If form is not valid or spam is detected, increment rate limiting
attempts = cache.get(f"registration_attempts_{client_ip}", 0)
cache.set(f"registration_attempts_{client_ip}", attempts + 1, 3600) # One hour expiry

# If too many attempts, rate limit
if attempts >= 5:
cache.set(f"registration_limit_{client_ip}", True, 3600 * 24) # 24 hour ban
return HttpResponse("Too many failed attempts. Try again tomorrow.", status=429)

# Continue with regular registration logic
# ...

def get_client_ip(request):
x_forwarded_for = request.META.get('HTTP_X_FORWARDED_FOR')
if x_forwarded_for:
ip = x_forwarded_for.split(',')[0]
else:
ip = request.META.get('REMOTE_ADDR')
return ip

Real-World Example: User Registration with Profile and Avatar

Here's a more comprehensive example for a social network site:

python
# models.py
from django.db import models
from django.contrib.auth.models import User

class UserProfile(models.Model):
user = models.OneToOneField(User, on_delete=models.CASCADE, related_name='profile')
avatar = models.ImageField(upload_to='avatars/', default='avatars/default.png')
bio = models.TextField(max_length=500, blank=True)
website = models.URLField(max_length=200, blank=True)
location = models.CharField(max_length=100, blank=True)
birth_date = models.DateField(null=True, blank=True)

def __str__(self):
return f"{self.user.username}'s profile"
python
# forms.py
from django import forms
from django.contrib.auth.forms import UserCreationForm
from django.contrib.auth.models import User
from .models import UserProfile

class ExtendedUserCreationForm(UserCreationForm):
email = forms.EmailField(required=True)
first_name = forms.CharField(max_length=30)
last_name = forms.CharField(max_length=30)

class Meta:
model = User
fields = ('username', 'email', 'first_name', 'last_name', 'password1', 'password2')

class UserProfileForm(forms.ModelForm):
class Meta:
model = UserProfile
fields = ('avatar', 'bio', 'website', 'location', 'birth_date')
widgets = {
'birth_date': forms.DateInput(attrs={'type': 'date'}),
}
python
# views.py
def register_with_profile(request):
if request.method == 'POST':
user_form = ExtendedUserCreationForm(request.POST)
profile_form = UserProfileForm(request.POST, request.FILES)

if user_form.is_valid() and profile_form.is_valid():
user = user_form.save()

# Create user profile
profile = profile_form.save(commit=False)
profile.user = user
profile.save()

# Log user in
username = user_form.cleaned_data.get('username')
password = user_form.cleaned_data.get('password1')
user = authenticate(username=username, password=password)
login(request, user)

return redirect('profile')
else:
user_form = ExtendedUserCreationForm()
profile_form = UserProfileForm()

context = {
'user_form': user_form,
'profile_form': profile_form
}
return render(request, 'registration/register_with_profile.html', context)

Summary

In this tutorial, we've covered:

  1. Setting up Django's user authentication system
  2. Creating registration forms and views
  3. Implementing email verification
  4. Setting up templates for the registration process
  5. Creating a custom user model or profile
  6. Adding security measures like rate limiting
  7. Building a real-world example with user profiles

User registration is a critical feature for many web applications, and Django provides powerful tools to implement it securely and efficiently. By following the steps in this guide, you should now be able to implement a robust registration system in your Django project.

Additional Resources and Exercises

Resources

Exercises

  1. Basic Exercise: Implement a simple registration system without email verification.

  2. Intermediate Exercise: Add email verification to your registration system.

  3. Advanced Exercise: Create a registration system with:

    • Social authentication (Google, Facebook)
    • Custom user model
    • Profile picture upload
    • Password strength meter on the frontend
  4. Challenge: Build a complete authentication system with:

    • Registration with email verification
    • Password reset functionality
    • Account deletion
    • Two-factor authentication

By completing these exercises, you'll gain practical experience with Django's authentication system and be ready to implement sophisticated registration flows in your projects.



If you spot any mistakes on this website, please let me know at [email protected]. I’d greatly appreciate your feedback! :)