如何在Django中实现客户与企业两类不同用户的独立注册功能?
Django 双角色用户差异化注册实现方案
第一步:扩展用户模型,区分角色并拆分差异化属性
修改现有models.py文件,新增角色字段标识用户类型,差异化属性通过一对一关联的专属表存储,避免主表冗余:
# models.py 完整修改后代码 from django.db import models from django.contrib.auth.base_user import BaseUserManager from django.contrib.auth.models import AbstractUser from django.utils.translation import gettext_lazy as _ from rest_framework.authtoken.models import Token from django.db.models.signals import post_save from django.conf import settings from django.dispatch import receiver class UserManager(BaseUserManager): use_in_migrations = True def _create_user(self, email, password, **extra_fields): if not email: raise ValueError('The given email must be set') 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_user(self, email, password=None, is_staff=False, is_superuser=False, **extra_fields): extra_fields.setdefault('is_staff', is_staff) extra_fields.setdefault('is_superuser', is_superuser) return self._create_user(email, password, **extra_fields) class User(AbstractUser): # 角色类型选项 USER_TYPE_CHOICES = ( ('customer', '个人客户'), ('company', '企业用户'), ) username = None last_name = None first_name = None name = models.CharField(max_length=100) email = models.EmailField(_('email address'), unique=True) contact = models.CharField(max_length=100) # 新增角色字段,标识用户类型 user_type = models.CharField(max_length=20, choices=USER_TYPE_CHOICES, default='customer') # 建议修改为邮箱作为登录凭证,原id作为登录字段不符合常规使用习惯,需保留原逻辑可改回'id' USERNAME_FIELD = 'email' REQUIRED_FIELDS = ['contact', 'name'] objects = UserManager() # 个人客户独有属性表 class CustomerProfile(models.Model): user = models.OneToOneField(User, on_delete=models.CASCADE, related_name='customer_profile') # 以下为示例属性,可按需修改 age = models.IntegerField(blank=True, null=True, verbose_name='年龄') delivery_address = models.CharField(max_length=200, blank=True, verbose_name='收货地址') # 企业用户独有属性表 class CompanyProfile(models.Model): user = models.OneToOneField(User, on_delete=models.CASCADE, related_name='company_profile') # 以下为示例属性,可按需修改 business_license = models.CharField(max_length=100, verbose_name='统一社会信用代码') company_address = models.CharField(max_length=200, verbose_name='企业地址') business_scope = models.TextField(blank=True, verbose_name='经营范围') @receiver(post_save, sender=settings.AUTH_USER_MODEL) def create_auth_token(sender, instance=None, created=False, **kwargs): if created: Token.objects.create(user=instance)
修改完成后执行python manage.py makemigrations和python manage.py migrate同步数据库结构。
第二步:编写两类用户的注册表单
新建forms.py文件,分别定义两个注册表单,控制需要用户填写的字段和校验规则:
# forms.py from django import forms from .models import User, CustomerProfile, CompanyProfile # 个人客户注册表单 class CustomerRegisterForm(forms.ModelForm): password = forms.CharField(widget=forms.PasswordInput, label='登录密码') confirm_password = forms.CharField(widget=forms.PasswordInput, label='确认密码') class Meta: model = User fields = ['name', 'email', 'contact', 'password'] # 校验两次密码一致性 def clean_confirm_password(self): password = self.cleaned_data.get('password') confirm_password = self.cleaned_data.get('confirm_password') if password and confirm_password and password != confirm_password: raise forms.ValidationError("两次输入的密码不一致") return confirm_password class CustomerProfileForm(forms.ModelForm): class Meta: model = CustomerProfile fields = ['age', 'delivery_address'] # 企业用户注册表单 class CompanyRegisterForm(forms.ModelForm): password = forms.CharField(widget=forms.PasswordInput, label='登录密码') confirm_password = forms.CharField(widget=forms.PasswordInput, label='确认密码') class Meta: model = User fields = ['name', 'email', 'contact', 'password'] def clean_confirm_password(self): password = self.cleaned_data.get('password') confirm_password = self.cleaned_data.get('confirm_password') if password and confirm_password and password != confirm_password: raise forms.ValidationError("两次输入的密码不一致") return confirm_password class CompanyProfileForm(forms.ModelForm): class Meta: model = CompanyProfile fields = ['business_license', 'company_address', 'business_scope']
第三步:编写差异化注册视图
在views.py中编写两个视图,分别处理两类用户的注册逻辑:
# views.py from django.shortcuts import render, redirect from django.db import transaction from .forms import CustomerRegisterForm, CustomerProfileForm, CompanyRegisterForm, CompanyProfileForm # 个人客户注册逻辑 def customer_register(request): if request.method == 'POST': user_form = CustomerRegisterForm(request.POST) profile_form = CustomerProfileForm(request.POST) if user_form.is_valid() and profile_form.is_valid(): # 开启事务保证数据一致性 with transaction.atomic(): # 保存公共用户信息 user = user_form.save(commit=False) user.set_password(user_form.cleaned_data['password']) user.user_type = 'customer' user.save() # 保存个人客户专属信息 profile = profile_form.save(commit=False) profile.user = user profile.save() # 注册成功跳转登录页,可按需修改跳转路径 return redirect('login') else: user_form = CustomerRegisterForm() profile_form = CustomerProfileForm() return render(request, 'customer_register.html', { 'user_form': user_form, 'profile_form': profile_form }) # 企业用户注册逻辑 def company_register(request): if request.method == 'POST': user_form = CompanyRegisterForm(request.POST) profile_form = CompanyProfileForm(request.POST) if user_form.is_valid() and profile_form.is_valid(): with transaction.atomic(): user = user_form.save(commit=False) user.set_password(user_form.cleaned_data['password']) user.user_type = 'company' user.save() profile = profile_form.save(commit=False) profile.user = user profile.save() return redirect('login') else: user_form = CompanyRegisterForm() profile_form = CompanyProfileForm() return render(request, 'company_register.html', { 'user_form': user_form, 'profile_form': profile_form })
第四步:配置路由
在应用的urls.py中添加两个注册路径:
# urls.py from django.urls import path from . import views urlpatterns = [ # 现有路由保持不变 path('register/customer/', views.customer_register, name='customer_register'), path('register/company/', views.company_register, name='company_register'), ]
第五步:开发两个注册模板
分别创建templates/customer_register.html和templates/company_register.html两个模板文件,渲染对应的表单即可,示例模板结构:
<!-- customer_register.html 示例,企业注册模板仅需替换标题和提示文字即可 --> <!DOCTYPE html> <html> <head> <title>个人客户注册</title> </head> <body> <h2>个人客户注册</h2> <form method="post"> {% csrf_token %} {{ user_form.as_p }} {{ profile_form.as_p }} <button type="submit">提交注册</button> </form> </body> </html>
如果两类用户的差异化属性较少,也可以直接把所有字段放到主User表中,通过表单控制不同角色显示不同字段,减少表关联复杂度。
内容的提问来源于stack exchange,提问作者somya goyal
相关产品推荐
相关产品推荐

