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

Django中关联User模型仅用邮箱密码注册登录报错的解决方法

Got it, let's break down how to solve this problem. The root issue is that Django's default User model requires a username field, but you want to build auth flows that only use email and password. Here are two solid solutions, with the first being the best long-term approach:

Django officially recommends defining a custom user model at the start of your project—this lets you fully replace the default auth logic and use email as the primary identifier, no username required. Here's how to set it up:

Step 1: Create the Custom User Model

In your app's models.py, add this code:

from django.contrib.auth.models import AbstractBaseUser, BaseUserManager, PermissionsMixin
from django.db import models

class CustomUserManager(BaseUserManager):
    def create_user(self, email, password=None, **extra_fields):
        if not email:
            raise ValueError('You must provide an email address')
        # Normalize email (lowercase domain part)
        email = self.normalize_email(email)
        user = self.model(email=email, **extra_fields)
        user.set_password(password)
        user.save(using=self._db)
        return user

    def create_superuser(self, email, password=None, **extra_fields):
        # Set admin-specific flags
        extra_fields.setdefault('is_staff', True)
        extra_fields.setdefault('is_superuser', True)

        if extra_fields.get('is_staff') is not True:
            raise ValueError('Superusers must have is_staff=True')
        if extra_fields.get('is_superuser') is not True:
            raise ValueError('Superusers must have is_superuser=True')

        return self.create_user(email, password, **extra_fields)

class CustomUser(AbstractBaseUser, PermissionsMixin):
    email = models.EmailField(unique=True)
    is_active = models.BooleanField(default=True)
    is_staff = models.BooleanField(default=False)

    objects = CustomUserManager()

    # Use email as the login identifier instead of username
    USERNAME_FIELD = 'email'
    # No extra required fields beyond email and password
    REQUIRED_FIELDS = []

    def __str__(self):
        return self.email

Step 2: Update Project Settings

In your settings.py, tell Django to use your custom user model:

AUTH_USER_MODEL = 'your_app_name.CustomUser'

Important: This must be set before running your first migrate command. If you've already migrated, you'll need to reset your database or create a migration to switch models (which is more complex).

Step 3: Build Auth Views & Forms

You can now create registration and login views that only ask for email and password. For example, a registration form:

from django import forms
from .models import CustomUser

class CustomUserCreationForm(forms.ModelForm):
    password1 = forms.CharField(label='Password', widget=forms.PasswordInput)
    password2 = forms.CharField(label='Confirm Password', widget=forms.PasswordInput)

    class Meta:
        model = CustomUser
        fields = ('email',)

    def clean_password2(self):
        # Verify password match
        password1 = self.cleaned_data.get("password1")
        password2 = self.cleaned_data.get("password2")
        if password1 and password2 and password1 != password2:
            raise forms.ValidationError("Passwords don't match")
        return password2

    def save(self, commit=True):
        # Save the hashed password
        user = super().save(commit=False)
        user.set_password(self.cleaned_data["password1"])
        if commit:
            user.save()
        return user

And a registration view:

from django.contrib.auth import login
from django.shortcuts import render, redirect
from .forms import CustomUserCreationForm

def register(request):
    if request.method == 'POST':
        form = CustomUserCreationForm(request.POST)
        if form.is_valid():
            user = form.save()
            login(request, user)
            return redirect('home')
    else:
        form = CustomUserCreationForm()
    return render(request, 'auth/register.html', {'form': form})
2. Auto-Generate Username for Default User (Temporary Workaround)

If you can't switch to a custom user model right now, you can auto-generate a username when creating users (using the email to avoid manual input). This is a quick fix but not ideal for long-term maintenance:

Example Registration View

from django.contrib.auth.models import User
from django.contrib.auth import authenticate, login
import hashlib
import random

def register(request):
    if request.method == 'POST':
        email = request.POST.get('email')
        password = request.POST.get('password')

        # Generate a unique username from the email (e.g., MD5 hash truncated to 15 chars)
        username = hashlib.md5(email.encode()).hexdigest()[:15]
        # Handle username collisions
        while User.objects.filter(username=username).exists():
            username += str(random.randint(0,9))

        # Create the user with auto-generated username
        user = User.objects.create_user(username=username, email=email, password=password)
        # Link to your OneToOne model here if needed
        # YourProfileModel.objects.create(user=user)

        # Log the user in
        authenticated_user = authenticate(request, username=user.username, password=password)
        if authenticated_user:
            login(request, authenticated_user)
            return redirect('home')
    return render(request, 'auth/register.html')

Adjust Login to Use Email

Since users will log in with email, modify your login view to look up the user by email:

def login_view(request):
    if request.method == 'POST':
        email = request.POST.get('email')
        password = request.POST.get('password')
        user = User.objects.filter(email=email).first()
        if user and authenticate(request, username=user.username, password=password):
            login(request, user)
            return redirect('home')
        # Add error handling for invalid credentials
    return render(request, 'auth/login.html')

Final Note

Stick with the custom user model if you can—it's the cleanest, most scalable solution. The auto-generated username workaround works for quick tests but can cause headaches down the line (like username collisions or limited flexibility for adding user fields).

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.05.07 07:32:35