You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

Django注册邮件验证失效:用户未验证链接即被创建

Fix: Django Email Verification - Prevent Account Creation Before Confirmation

Got it, let's fix this issue right away. The problem with the original implementation is that it creates an active user account immediately when someone signs up. We need to adjust the flow so the account stays inactive until the user clicks the verification link in their email. Here's how to do it step by step:

1. Create an Inactive User on Registration

Instead of creating an active user by default, set is_active=False when saving the user. This blocks them from logging in until they verify their email.

Update your registration view code:

from django.contrib.auth.models import User
from django.contrib.sites.shortcuts import get_current_site
from django.core.mail import EmailMessage
from django.template.loader import render_to_string
from django.utils.encoding import force_bytes, force_text
from django.utils.http import urlsafe_base64_encode

def register(request):
    if request.method == 'POST':
        # Get form data (adjust based on your form structure)
        username = request.POST['username']
        email = request.POST['email']
        password = request.POST['password']
        
        # Create user but keep it inactive initially
        user = User.objects.create_user(username=username, email=email, password=password)
        user.is_active = False  # This is the critical line!
        user.save()
        
        # Generate verification token and send email (continue to step 2)
        # ... rest of your email logic here
    # Handle GET requests or form validation errors
    # ...

2. Generate a Secure Verification Token

We'll use Django's built-in token generator to create a unique, time-limited token for each user. Create a custom token generator (save this in a tokens.py file in your app):

from django.contrib.auth.tokens import PasswordResetTokenGenerator
from django.utils import six

class AccountActivationTokenGenerator(PasswordResetTokenGenerator):
    def _make_hash_value(self, user, timestamp):
        # Include user's active status to invalidate tokens if account is activated early
        return (
            six.text_type(user.pk) + six.text_type(timestamp) +
            six.text_type(user.is_active)
        )

account_activation_token = AccountActivationTokenGenerator()

3. Send the Verification Email

In your registration view, add code to build the verification URL and send it to the user's email:

from .tokens import account_activation_token

# Inside the POST block of your register view:
current_site = get_current_site(request)
mail_subject = 'Activate your account'
message = render_to_string('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 = email  # Use the email submitted in the form
email = EmailMessage(mail_subject, message, to=[to_email])
email.send()

# Redirect to a page telling the user to check their inbox
return redirect('registration_success')

Create the email template (account_activation_email.html) with the verification link:

Hi {{ user.username }},

Please click the link below to activate your account:

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

If you didn't request this, feel free to ignore this email.

4. Create the Activation View

Add a view to handle the verification link click, validate the token, and activate the user:

from django.shortcuts import redirect, HttpResponse
from django.utils.http import urlsafe_base64_decode
from django.contrib.auth import login
from .tokens import account_activation_token

def activate(request, uidb64, token):
    try:
        # Decode the user ID from the URL parameters
        uid = force_text(urlsafe_base64_decode(uidb64))
        user = User.objects.get(pk=uid)
    except (TypeError, ValueError, OverflowError, User.DoesNotExist):
        user = None
    
    # Validate token and activate the user if everything checks out
    if user is not None and account_activation_token.check_token(user, token):
        user.is_active = True
        user.save()
        login(request, user)  # Auto-login after activation (optional)
        return redirect('home')  # Redirect to your app's home page
    else:
        return HttpResponse('Activation link is invalid or has expired.')

5. Update Your URLs

Add a URL pattern for the activation view in your app's urls.py:

from django.urls import path
from . import views

urlpatterns = [
    # ... your existing URLs
    path('activate/<uidb64>/<token>/', views.activate, name='activate'),
]

Key Notes

  • Django's Default Login Check: Django's built-in authentication system automatically blocks inactive users from logging in, so you don't need extra code to enforce this.
  • Email Testing: For development, use the console backend to view emails directly in your terminal:
    # In settings.py
    EMAIL_BACKEND = 'django.core.mail.backends.console.EmailBackend'
    
  • Token Expiry: The default token expires after 3 days. If you need a different timeframe, override the _num_days method in your custom token generator.

内容的提问来源于stack exchange,提问作者omkar more

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.05.07 13:57:51