Django中基于自定义模型实现邮箱登录的最优方案求助
Hey Gabriel, I see you're struggling to get login working with your custom UserRegister model—let's walk through the issues and fix this together.
First, the core problem is that your current model doesn’t integrate with Django’s built-in authentication system, which expects specific fields and methods to handle password hashing, authentication, and user management. Here’s what’s missing and how to fix it:
Key Issues in Your Current Model
- You’re storing two password fields (
password1/password2)—these are for registration validation, not database storage. We only need one hashed password field in the DB. - Your model doesn’t inherit from Django’s authentication base classes (
AbstractBaseUserorAbstractUser), which provide critical methods likeset_password()andcheck_password()that the auth system relies on. - Django isn’t configured to use your custom model as the default user model.
Revised Model Implementation
Let’s update your models.py to align with Django’s auth requirements. We’ll use AbstractBaseUser for full control over fields, plus PermissionsMixin to handle permissions:
from django.db import models from django.contrib.auth.models import AbstractBaseUser, BaseUserManager, PermissionsMixin from .choices import gender_choices, marital_status, districts class UserRegisterManager(BaseUserManager): def create_user(self, email, password=None, **extra_fields): # Validate required fields if not email: raise ValueError('Users must have an email address') # Normalize email (lowercase domain) email = self.normalize_email(email) user = self.model(email=email, **extra_fields) # Hash the password automatically user.set_password(password) user.save(using=self._db) return user def create_superuser(self, email, password=None, **extra_fields): # Set admin defaults extra_fields.setdefault('is_staff', True) extra_fields.setdefault('is_superuser', True) if extra_fields.get('is_staff') is not True: raise ValueError('Superuser must have is_staff=True.') if extra_fields.get('is_superuser') is not True: raise ValueError('Superuser must have is_superuser=True.') return self.create_user(email, password, **extra_fields) class UserRegister(AbstractBaseUser, PermissionsMixin): name = models.CharField(max_length=30) email = models.EmailField(unique=True) # Make email unique for login is_active = models.BooleanField(default=True) is_staff = models.BooleanField(default=False) # Your custom fields termo_resp = models.BooleanField() gender = models.CharField(choices=gender_choices, max_length=1, null=True) birthdate = models.DateField(blank=True, null=True) marital_status = models.CharField(choices=marital_status, max_length=1, null=True) districts = models.CharField(choices=districts, max_length=20, null=True) city = models.CharField(max_length=25, null=True) job = models.CharField(max_length=50, null=True) # Specify the field used for login (email instead of username) USERNAME_FIELD = 'email' # Required fields for createsuperuser (add any others you need) REQUIRED_FIELDS = ['name'] # Attach our custom manager objects = UserRegisterManager() def __str__(self): return self.email
Critical Configuration Step
Add this line to your project’s settings.py to tell Django to use your custom model as the default user model:
AUTH_USER_MODEL = 'your_app_name.UserRegister'
(Replace your_app_name with the actual name of the app containing this model.)
How to Handle Registration & Login
Registration View
When handling user registration, validate that password1 and password2 match, then use the manager’s create_user() method to save the user (this automatically hashes the password):
from django.shortcuts import render, redirect from .models import UserRegister def register(request): if request.method == 'POST': name = request.POST['name'] email = request.POST['email'] password1 = request.POST['password1'] password2 = request.POST['password2'] termo_resp = request.POST.get('termo_resp') == 'on' # Validate passwords match if password1 != password2: return render(request, 'register.html', {'error': 'Passwords do not match'}) # Create user using our manager UserRegister.objects.create_user( email=email, password=password1, name=name, termo_resp=termo_resp, # Add other custom fields from POST data as needed ) return redirect('login') return render(request, 'register.html')
Login View
Use Django’s built-in authenticate() and login() functions to handle login (they’ll work with your custom model now):
from django.contrib.auth import authenticate, login from django.shortcuts import render, redirect def user_login(request): if request.method == 'POST': email = request.POST['email'] password = request.POST['password'] # Authenticate using email and password user = authenticate(request, email=email, password=password) if user is not None: login(request, user) return redirect('home') # Redirect to your app's home page else: return render(request, 'login.html', {'error': 'Invalid email or password'}) return render(request, 'login.html')
Important Notes
- If you already ran migrations before creating this custom model, you’ll need to reset your database (or manually adjust migration files) because Django can’t easily change the auth model after initial migrations.
- Make sure any forms (like registration forms) reference your custom model if you’re using Django’s form classes.
With these changes, your custom user model should work seamlessly with Django’s authentication system, allowing users to register and log in successfully.
内容的提问来源于stack exchange,提问作者Gabriel costa

