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

如何在Django中不扩展User模型创建独立用户库及Agent独立登录

问题

我正在用Django搭建网站,需要创建users和agents两个独立用户库,Agent不需要关联User就能独立存在,而且两者要有各自独立的登录URL。现在我没法给Agent创建独立登录页面;另外,任何人不用登录/注册成User就能申请成为Agent,满足条件后由超级管理员在后台完成Agent的注册。想问问有没有更优的实现方案?


当前代码实现

models.py

from django.contrib.auth.models import User

class Profile(models.Model):
    user = models.OneToOneField(User, on_delete=models.CASCADE)
    phonenumber = models.IntegerField()

    def __str__(self):
        return f'{self.user.username} Profile'

class Agent(models.Model):
    name = models.CharField(max_length=100)
    password = models.CharField(max_length=100)
    image = models.ImageField(upload_to = 'Images/')
    bio = models.TextField()
    instagram = models.URLField(max_length=100)
    twitter = models.URLField(max_length=100)
    facebook = models.URLField(max_length=100)
    linkedin = models.URLField(max_length=100)
    is_featured = models.BooleanField(default = False)
    slug = models.SlugField(default='')

    def __str__(self):
        return f'{self.name} Agent Profile'

forms.py

class AgentSignInForm(AuthenticationForm):
    username = forms.CharField(max_length=100)
    password = forms.CharField(max_length=100)
    def clean(self):
        cleaned_data = super().clean()
        username = cleaned_data.get('username')
        password = cleaned_data.get('password')
        return cleaned_data

views.py

class AgentLoginView(LoginView):
    form_class = AgentSignInForm
    def form_valid(self, form):
        form.send_email()
        return super().form_valid(form)

urls.py

urlpatterns = [
path('agent-sign-in/', auth_views.LoginView.as_view(template_name='users/agent_login.html'), name='agent-sign-in'),
]

优化实现方案

一、重构Agent模型,适配Django认证系统

当前Agent模型直接存储明文密码存在严重安全问题,应该基于Django的AbstractBaseUser实现独立的Agent用户模型,既复用Django的认证能力,又保持与默认User模型的独立性。

修改models.py

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

# 保留原有Profile模型,关联默认User
class Profile(models.Model):
    user = models.OneToOneField(User, on_delete=models.CASCADE)
    phonenumber = models.IntegerField()

    def __str__(self):
        return f'{self.user.username} Profile'

# Agent用户管理器,处理账号创建逻辑
class AgentManager(BaseUserManager):
    def create_user(self, name, password=None, **extra_fields):
        if not name:
            raise ValueError('Agent必须填写姓名')
        agent = self.model(name=name, **extra_fields)
        agent.set_password(password)  # 加密存储密码
        agent.save(using=self._db)
        return agent

    def create_superuser(self, name, password=None, **extra_fields):
        extra_fields.setdefault('is_staff', True)
        extra_fields.setdefault('is_superuser', True)
        return self.create_user(name, password, **extra_fields)

# 独立的Agent用户模型
class Agent(AbstractBaseUser, PermissionsMixin):
    name = models.CharField(max_length=100, unique=True)  # 用姓名作为登录标识,设为唯一
    image = models.ImageField(upload_to='Images/', blank=True, null=True)
    bio = models.TextField(blank=True)
    instagram = models.URLField(max_length=100, blank=True)
    twitter = models.URLField(max_length=100, blank=True)
    facebook = models.URLField(max_length=100, blank=True)
    linkedin = models.URLField(max_length=100, blank=True)
    is_featured = models.BooleanField(default=False)
    slug = models.SlugField(default='', unique=True)
    is_active = models.BooleanField(default=True)  # 控制账号是否可登录
    is_staff = models.BooleanField(default=False)  # 控制是否能访问后台

    objects = AgentManager()

    USERNAME_FIELD = 'name'  # 指定登录用的字段
    REQUIRED_FIELDS = []

    def __str__(self):
        return f'{self.name} Agent Profile'

二、配置双用户认证后端

在项目的settings.py中添加自定义认证后端,让Django支持同时识别默认User和Agent两种用户:

settings.py

AUTHENTICATION_BACKENDS = [
    'django.contrib.auth.backends.ModelBackend',  # 默认User的认证后端
    '你的应用名.backends.AgentBackend',  # 自定义Agent认证后端
]

在应用目录下创建backends.py,编写Agent认证逻辑:

from django.contrib.auth.backends import ModelBackend
from .models import Agent

class AgentBackend(ModelBackend):
    def authenticate(self, request, username=None, password=None, **kwargs):
        try:
            agent = Agent.objects.get(name=username)
            if agent.check_password(password) and agent.is_active:
                return agent
        except Agent.DoesNotExist:
            return None

    def get_user(self, user_id):
        try:
            return Agent.objects.get(pk=user_id)
        except Agent.DoesNotExist:
            return None

三、实现Agent独立登录流程

修改forms.py

针对Agent模型编写登录表单,增加密码验证逻辑:

from django import forms
from django.contrib.auth.forms import AuthenticationForm
from .models import Agent

class AgentSignInForm(AuthenticationForm):
    username = forms.CharField(label='姓名', max_length=100)
    password = forms.CharField(label='密码', widget=forms.PasswordInput)

    def clean(self):
        cleaned_data = super().clean()
        name = cleaned_data.get('username')
        password = cleaned_data.get('password')
        
        try:
            agent = Agent.objects.get(name=name)
            if not agent.check_password(password):
                raise forms.ValidationError('密码错误')
            if not agent.is_active:
                raise forms.ValidationError('该账号未激活')
        except Agent.DoesNotExist:
            raise forms.ValidationError('不存在该Agent账号')
        
        return cleaned_data

修改views.py

自定义Agent登录视图,指定使用Agent认证后端:

from django.contrib.auth import login, authenticate
from django.views.generic import FormView
from .forms import AgentSignInForm

class AgentLoginView(FormView):
    form_class = AgentSignInForm
    template_name = 'users/agent_login.html'
    success_url = '/agent-dashboard/'  # Agent登录后的跳转页面

    def form_valid(self, form):
        name = form.cleaned_data.get('username')
        password = form.cleaned_data.get('password')
        # 指定使用Agent后端认证
        agent = authenticate(self.request, username=name, password=password, backend='你的应用名.backends.AgentBackend')
        
        if agent:
            login(self.request, agent)
            return super().form_valid(form)
        else:
            form.add_error(None, '登录失败,请检查账号密码')
            return self.form_invalid(form)

修改urls.py

使用自定义的Agent登录视图,替换默认的auth_views:

from django.urls import path
from .views import AgentLoginView
from django.contrib.auth import views as auth_views

urlpatterns = [
    # Agent独立登录URL
    path('agent-sign-in/', AgentLoginView.as_view(), name='agent-sign-in'),
    # Agent登出URL
    path('agent-sign-out/', auth_views.LogoutView.as_view(next_page='/'), name='agent-sign-out'),
    # 保留默认User的登录URL(如果需要)
    path('user-sign-in/', auth_views.LoginView.as_view(template_name='users/user_login.html'), name='user-sign-in'),
]

四、实现Agent申请与后台审核流程

1. 创建Agent申请模型(存储申请记录)

class AgentApplication(models.Model):
    name = models.CharField(max_length=100)
    email = models.EmailField()  # 用于联系申请人
    phonenumber = models.CharField(max_length=20)
    bio = models.TextField()
    instagram = models.URLField(max_length=100, blank=True)
    twitter = models.URLField(max_length=100, blank=True)
    facebook = models.URLField(max_length=100, blank=True)
    linkedin = models.URLField(max_length=100, blank=True)
    applied_at = models.DateTimeField(auto_now_add=True)
    is_approved = models.BooleanField(default=False)

    def __str__(self):
        return f'{self.name}的Agent申请'

2. 申请表单与视图

# forms.py
class AgentApplicationForm(forms.ModelForm):
    class Meta:
        model = AgentApplication
        fields = ['name', 'email', 'phonenumber', 'bio', 'instagram', 'twitter', 'facebook', 'linkedin']

# views.py
from django.views.generic.edit import CreateView
from .models import AgentApplication

class AgentApplyView(CreateView):
    form_class = AgentApplicationForm
    template_name = 'users/agent_apply.html'
    success_url = '/apply-success/'  # 申请提交后的跳转页面

    def form_valid(self, form):
        form.save()
        return super().form_valid(form)

3. 后台配置

在admin.py中注册模型,让超级管理员可以审核申请并创建正式Agent账号:

from django.contrib import admin
from .models import Profile, Agent, AgentApplication

admin.site.register(Profile)
admin.site.register(Agent)
admin.site.register(AgentApplication)

审核时,管理员可从申请记录中提取信息,直接创建Agent账号并设置初始密码,再通知申请人。

五、模板适配

在模板中可通过request.user判断用户类型,展示对应内容:

{% if user.is_authenticated %}
    {% if user.__class__.__name__ == 'Agent' %}
        <p>欢迎,Agent {{ user.name }}</p>
        <a href="{% url 'agent-sign-out' %}">登出</a>
    {% else %}
        <p>欢迎,用户 {{ user.username }}</p>
        <a href="{% url 'user-sign-out' %}">登出</a>
    {% endif %}
{% else %}
    <a href="{% url 'agent-sign-in' %}">Agent登录</a>
    <a href="{% url 'user-sign-in' %}">用户登录</a>
    <a href="{% url 'agent-apply' %}">申请成为Agent</a>
{% endif %}

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.07.03 19:14:50