如何在Django中用两个模型扩展User模型实现双注册面板?
要实现企业(Company)和职位申请者(这里建议把Vacancy改名为Applicant更贴合语义哦)两个角色的独立注册,核心是把Django自带的User模型和你的业务模型关联起来,同时为不同角色搭建专属的注册流程。下面我给你梳理两种常用的实现方案,还有具体的代码示例:
方案一:一对一关联现有模型(适合已有业务模型的场景)
这种方式不需要修改Django默认的User模型,只需要给Company和Applicant添加一对一关联字段,绑定到User即可,兼容性强、改动小。
1. 修改模型,添加一对一关联
调整你的现有模型,新增user字段关联Django的User:
from django.contrib.auth.models import User from django.db import models class Company(models.Model): # 一对一关联User,on_delete确保用户删除时企业信息同步删除 user = models.OneToOneField(User, on_delete=models.CASCADE, related_name='company') name_company = models.CharField(max_length=100) city = models.CharField(max_length=100) street = models.CharField(max_length=100) phone = models.CharField(max_length=9) email = models.EmailField(max_length=50) class Applicant(models.Model): # 重命名为Applicant更符合“职位申请者”的定位 user = models.OneToOneField(User, on_delete=models.CASCADE, related_name='applicant') fullname = models.CharField(max_length=100) age = models.IntegerField(blank=True, default=0) education = models.CharField(max_length=100, blank=True, default='') origin = models.CharField(max_length=100, blank=True, default='') miasto = models.CharField(max_length=100, blank=True, default='') panstwo = models.CharField(max_length=100, blank=True, default='')
小提示:
related_name参数可以让你通过User实例快速访问关联的业务模型,比如request.user.company就能直接拿到当前登录企业的信息,非常方便。
2. 创建独立的注册表单
为企业和申请者分别编写专属表单,把User的账号字段(用户名、密码)和业务模型的字段整合在一起:
企业注册表单
from django import forms from django.contrib.auth.forms import UserCreationForm from django.contrib.auth.models import User from .models import Company class CompanyRegistrationForm(UserCreationForm): # 新增企业专属字段 name_company = forms.CharField(max_length=100) city = forms.CharField(max_length=100) street = forms.CharField(max_length=100) phone = forms.CharField(max_length=9) email = forms.EmailField(max_length=50) class Meta: model = User fields = ['username', 'password1', 'password2'] # User的核心账号字段 def save(self, commit=True): # 先保存User实例 user = super().save(commit=False) if commit: user.save() # 同步创建关联的Company实例 Company.objects.create( user=user, name_company=self.cleaned_data['name_company'], city=self.cleaned_data['city'], street=self.cleaned_data['street'], phone=self.cleaned_data['phone'], email=self.cleaned_data['email'] ) return user
申请者注册表单
from django import forms from django.contrib.auth.forms import UserCreationForm from django.contrib.auth.models import User from .models import Applicant class ApplicantRegistrationForm(UserCreationForm): fullname = forms.CharField(max_length=100) age = forms.IntegerField(required=False) education = forms.CharField(max_length=100, required=False) origin = forms.CharField(max_length=100, required=False) miasto = forms.CharField(max_length=100, required=False) panstwo = forms.CharField(max_length=100, required=False) class Meta: model = User fields = ['username', 'password1', 'password2'] def save(self, commit=True): user = super().save(commit=False) if commit: user.save() # 同步创建关联的Applicant实例 Applicant.objects.create( user=user, fullname=self.cleaned_data['fullname'], age=self.cleaned_data.get('age', 0), education=self.cleaned_data.get('education', ''), origin=self.cleaned_data.get('origin', ''), miasto=self.cleaned_data.get('miasto', ''), panstwo=self.cleaned_data.get('panstwo', '') ) return user
3. 编写注册视图
为两个角色分别写视图,处理表单提交逻辑:
from django.shortcuts import render, redirect from .forms import CompanyRegistrationForm, ApplicantRegistrationForm def company_register(request): if request.method == 'POST': form = CompanyRegistrationForm(request.POST) if form.is_valid(): form.save() return redirect('login') # 注册成功跳转到登录页 else: form = CompanyRegistrationForm() return render(request, 'company_register.html', {'form': form}) def applicant_register(request): if request.method == 'POST': form = ApplicantRegistrationForm(request.POST) if form.is_valid(): form.save() return redirect('login') else: form = ApplicantRegistrationForm() return render(request, 'applicant_register.html', {'form': form})
4. 配置URL和模板
在urls.py中添加两个注册路由:
from django.urls import path from .views import company_register, applicant_register urlpatterns = [ path('register/company/', company_register, name='company_register'), path('register/applicant/', applicant_register, name='applicant_register'), # 其他URL... ]
然后分别创建company_register.html和applicant_register.html模板,渲染对应的表单即可,示例模板代码:
<form method="post"> {% csrf_token %} {{ form.as_p }} <button type="submit">注册企业账号</button> </form>
方案二:自定义User模型(适合项目初期)
如果你的项目还处于起步阶段,可以直接继承AbstractUser创建专属用户模型,这种方式更贴合角色定位,但需要提前配置默认用户模型:
1. 创建自定义用户模型
from django.contrib.auth.models import AbstractUser from django.db import models class CompanyUser(AbstractUser): name_company = models.CharField(max_length=100) city = models.CharField(max_length=100) street = models.CharField(max_length=100) phone = models.CharField(max_length=9) email = models.EmailField(max_length=50) class ApplicantUser(AbstractUser): fullname = models.CharField(max_length=100) age = models.IntegerField(blank=True, default=0) education = models.CharField(max_length=100, blank=True, default='') origin = models.CharField(max_length=100, blank=True, default='') miasto = models.CharField(max_length=100, blank=True, default='') panstwo = models.CharField(max_length=100, blank=True, default='')
然后在settings.py中配置默认用户模型:
AUTH_USER_MODEL = 'yourapp.CompanyUser' # 注意:Django仅支持设置一个默认用户模型,若要区分多角色,需配合自定义认证后端或权限库(如django-guardian)
额外思路:用角色字段区分用户
如果不想拆分模型,也可以在User模型里添加role字段(比如choices=[('company', '企业'), ('applicant', '申请者')]),然后用一个表单根据选中的角色动态显示不同字段。不过这种方式后期扩展灵活性不如一对一关联,适合业务逻辑简单的场景。
内容的提问来源于stack exchange,提问作者Raba_Ababa

