Django注册页面添加邮箱验证功能需求咨询(含代码片段)
Alright, let's walk through adding email verification to your Django signup flow step by step. I'll cover everything from extending the user model to sending verification emails and handling token validation—no third-party packages required (unless you want to use them later!).
First, we need to track whether a user's email is verified and store a secure verification token. We'll use a UserProfile model linked to Django's default User via a one-to-one relationship (skip this if you're already using a custom user model):
# your_app/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 UserProfile(models.Model): user = models.OneToOneField(User, on_delete=models.CASCADE) is_email_verified = models.BooleanField(default=False) verification_token = models.CharField(max_length=200, blank=True) # Auto-create a profile whenever a new User is created @receiver(post_save, sender=User) def create_user_profile(sender, instance, created, **kwargs): if created: UserProfile.objects.create(user=instance) @receiver(post_save, sender=User) def save_user_profile(sender, instance, **kwargs): instance.userprofile.save()
Use Django's built-in signing module to generate tamper-proof, time-limited tokens (this is more secure than storing random strings without expiration):
# your_app/utils.py from django.core.signing import TimestampSigner, BadSignature, SignatureExpired def generate_verification_token(user): # Adds a timestamp to the token so we can enforce expiration signer = TimestampSigner() return signer.sign(user.id) def verify_verification_token(token, max_age=86400): # Token expires after 24 hours (86400 seconds) signer = TimestampSigner() try: user_id = signer.unsign(token, max_age=max_age) return user_id except (BadSignature, SignatureExpired): return None
Update your signup view to create a non-active user (so they can't log in until verified), generate a token, and send the verification email:
# your_app/views.py from django.shortcuts import render, redirect from django.contrib.auth.models import User from django.core.mail import send_mail from django.conf import settings from django.contrib import messages from .models import UserProfile from .utils import generate_verification_token def signup(request): if request.method == 'POST': username = request.POST.get('username') email = request.POST.get('email') password = request.POST.get('password') # Basic validation (add more as needed) if User.objects.filter(username=username).exists(): messages.error(request, 'Username already taken.') return redirect('signup') if User.objects.filter(email=email).exists(): messages.error(request, 'Email already registered.') return redirect('signup') # Create user but keep them inactive user = User.objects.create_user( username=username, email=email, password=password ) user.is_active = False user.save() # Generate token and update profile token = generate_verification_token(user) profile = UserProfile.objects.get(user=user) profile.verification_token = token profile.save() # Build the verification URL verification_url = f"{request.scheme}://{request.get_host()}/verify-email/{token}/" # Send the verification email subject = 'Verify Your Email for Our App' message = f"""Hi {username}, Thanks for signing up! Please click the link below to verify your email address: {verification_url} This link will expire in 24 hours. If you didn't create an account with us, feel free to ignore this email. Best regards, The Team """ send_mail( subject, message, settings.DEFAULT_FROM_EMAIL, [email], fail_silently=False, ) return render(request, 'fir/verification_sent.html') # GET request: render the signup form return render(request, 'fir/signup.html')
This view will validate the token, activate the user, and mark their email as verified:
# your_app/views.py (add this function) from .utils import verify_verification_token def verify_email(request, token): user_id = verify_verification_token(token) if not user_id: messages.error(request, 'Invalid or expired verification link. Please request a new one.') return redirect('signup') try: user = User.objects.get(id=user_id) profile = UserProfile.objects.get(user=user) except (User.DoesNotExist, UserProfile.DoesNotExist): messages.error(request, 'User not found.') return redirect('signup') if profile.is_email_verified: messages.info(request, 'Your email is already verified. You can log in now.') return redirect('login') # Activate the user and mark email as verified user.is_active = True profile.is_email_verified = True user.save() profile.save() messages.success(request, 'Email verified successfully! You can now log in.') return redirect('login')
Add the verification endpoint to your app's urls.py:
# your_app/urls.py from django.urls import path from . import views urlpatterns = [ path('signup/', views.signup, name='signup'), path('verify-email/<str:token>/', views.verify_email, name='verify_email'), # Add your login URL here if it's not already present path('login/', views.login_view, name='login'), ]
Make a simple template to confirm the email was sent to the user:
<!-- fir/verification_sent.html --> {% extends 'fir/base_visitor.html' %} {% block title %}Verification Sent{% endblock %} {% block body %} <div class="container-fluid"> <div class="row justify-content-center"> <div class="col-sm-12 col-md-6"> <div class="panel panel-default"> <div class="panel-heading"> <h3 class="panel-title">Check Your Email</h3> </div> <div class="panel-body"> <p>We've sent a verification link to <strong>{{ request.POST.email }}</strong>. Please click it to complete your registration.</p> <p>If you don't see the email within a few minutes, check your spam or junk folder.</p> <a href="{% url 'signup' %}" class="btn btn-default">Back to Signup</a> </div> </div> </div> </div> </div> {% endblock %}
In your settings.py, set up the email backend to send emails. For example, using Gmail (use an app password if 2FA is enabled):
# settings.py EMAIL_BACKEND = 'django.core.mail.backends.smtp.EmailBackend' EMAIL_HOST = 'smtp.gmail.com' EMAIL_PORT = 587 EMAIL_USE_TLS = True EMAIL_HOST_USER = 'your-email@gmail.com' EMAIL_HOST_PASSWORD = 'your-app-password-or-email-password' DEFAULT_FROM_EMAIL = 'your-email@gmail.com'
If users don't get the email, add a view to resend the verification link:
# views.py def resend_verification(request): if request.method == 'POST': email = request.POST.get('email') try: user = User.objects.get(email=email, is_active=False) profile = UserProfile.objects.get(user=user) token = generate_verification_token(user) profile.verification_token = token profile.save() verification_url = f"{request.scheme}://{request.get_host()}/verify-email/{token}/" subject = 'Resend: Verify Your Email Address' message = f"""Hi {user.username}, Here's your new verification link: {verification_url} This link expires in 24 hours. Best regards, The Team """ send_mail(subject, message, settings.DEFAULT_FROM_EMAIL, [email]) messages.success(request, 'New verification link sent to your email.') return redirect('resend_verification') except User.DoesNotExist: messages.error(request, 'No inactive account found with this email.') return redirect('resend_verification') return render(request, 'fir/resend_verification.html')
Just add a corresponding template and URL for this view, and you're set!
内容的提问来源于stack exchange,提问作者Afreen Khan

