自定义用户模型完整案例 - 集成注册、登录、退出、修改视图函数

一、项目结构
myproject/
├── myproject/
│   ├── settings.py
│   ├── urls.py
├── users/
│   ├── models.py       # 关联模型
│   ├── forms.py        # 表单定义
│   ├── views.py        # 视图函数
│   ├── urls.py         # 子路由
│   ├── templates/
│   │   ├── register.html
│   │   ├── login.html
│   │   ├── profile.html
│   │   └── edit_profile.html

二、模型定义
# users/models.py
from django.db import models
from django.contrib.auth.models import User

class Profile(models.Model):
    user = models.OneToOneField(
        User, 
        on_delete=models.CASCADE,
        related_name='profile'
    )
    mobile = models.CharField('手机号', max_length=11, unique=True)
    avatar = models.ImageField('头像', upload_to='avatars/', blank=True)
    bio = models.TextField('个人简介', blank=True)

    def __str__(self):
        return f"{self.user.username} 的扩展资料"

三、表单定义
# users/forms.py
from django import forms
from django.contrib.auth.forms import UserCreationForm
from django.contrib.auth.models import User
from .models import Profile

class SignupForm(UserCreationForm):
    mobile = forms.CharField(max_length=11, required=True)
    avatar = forms.ImageField(required=False)

    class Meta(UserCreationForm.Meta):
        fields = ('username', 'email', 'password1', 'password2', 'mobile')

    def save(self, commit=True):
        user = super().save(commit=False)
        user.email = self.cleaned_data['email']
        if commit:
            user.save()
            # 创建关联的Profile对象
            Profile.objects.create(
                user=user,
                mobile=self.cleaned_data['mobile'],
                avatar=self.cleaned_data['avatar']
            )
        return user

class UserEditForm(forms.ModelForm):
    class Meta:
        model = User
        fields = ['username', 'email', 'first_name', 'last_name']

class ProfileEditForm(forms.ModelForm):
    class Meta:
        model = Profile
        fields = ['mobile', 'avatar', 'bio']

四、视图实现
# users/views.py
from django.shortcuts import render, redirect
from django.contrib.auth import authenticate, login, logout
from django.contrib.auth.decorators import login_required
from .forms import SignupForm, UserEditForm, ProfileEditForm

def register(request):
    if request.method == 'POST':
        form = SignupForm(request.POST, request.FILES)
        if form.is_valid():
            user = form.save()
            login(request, user)  # 注册后自动登录
            return redirect('profile')
    else:
        form = SignupForm()
    return render(request, 'users/register.html', {'form': form})

def user_login(request):
    if request.method == 'POST':
        username = request.POST.get('username')
        password = request.POST.get('password')
        user = authenticate(request, username=username, password=password)
        if user:
            login(request, user)
            return redirect('profile')
        else:
            return render(request, 'users/login.html', {'error': '用户名或密码错误'})
    return render(request, 'users/login.html')

@login_required
def user_logout(request):
    logout(request)
    return redirect('login')

@login_required
def profile(request):
    return render(request, 'users/profile.html')

@login_required
def edit_profile(request):
    if request.method == 'POST':
        user_form = UserEditForm(request.POST, instance=request.user)
        profile_form = ProfileEditForm(
            request.POST, 
            request.FILES, 
            instance=request.user.profile
        )
        if user_form.is_valid() and profile_form.is_valid():
            user_form.save()
            profile_form.save()
            return redirect('profile')
    else:
        user_form = UserEditForm(instance=request.user)
        profile_form = ProfileEditForm(instance=request.user.profile)
    
    return render(request, 'users/edit_profile.html', {
        'user_form': user_form,
        'profile_form': profile_form
    })

五、路由配置
# myproject/urls.py
from django.contrib import admin
from django.urls import path, include
from . import views

urlpatterns = [
    path('admin/', admin.site.urls),
    path('users/', include('users.urls')),
    path('register/', views.register, name='register'),
    path('login/', views.user_login, name='login'),
    path('logout/', views.user_logout, name='logout'),
    path('profile/', views.profile, name='profile'),
    path('edit/', views.edit_profile, name='edit_profile'),
]

六、模板示例
<!-- users/register.html -->
<form method="post" enctype="multipart/form-data">
  {% csrf_token %}
  {{ form.as_p }}
  <button class="btn btn-primary">注册</button>
  <p>已有账号?<a href="{% url 'login' %}">立即登录</a></p>
</form>

<!-- users/login.html -->
<form method="post">
  {% csrf_token %}
  <div class="form-group">
    <input type="text" name="username" placeholder="用户名" required>
  </div>
  <div class="form-group">
    <input type="password" name="password" placeholder="密码" required>
  </div>
  <button class="btn btn-primary">登录</button>
  <p>没有账号?<a href="{% url 'register' %}">注册新用户</a></p>
</form>

<!-- users/profile.html -->
<h2>欢迎回来,{{ user.username }}</h2>
<div class="profile-info">
  <img src="{{ user.profile.avatar.url }}" class="avatar">
  <p>📧 邮箱:{{ user.email }}</p>
  <p>📱 手机:{{ user.profile.mobile }}</p>
  <p>📝 简介:{{ user.profile.bio }}</p>
</div>
<a href="{% url 'edit_profile' %}" class="btn btn-secondary">编辑资料</a>
<a href="{% url 'logout' %}" class="btn btn-danger">退出登录</a>

<!-- users/edit_profile.html -->
<form method="post" enctype="multipart/form-data">
  {% csrf_token %}
  <div class="form-section">
    <h3>基础信息</h3>
    {{ user_form.as_p }}
  </div>
  <div class="form-section">
    <h3>扩展信息</h3>
    {{ profile_form.as_p }}
  </div>
  <button class="btn btn-success">保存修改</button>
</form>

七、关键配置
# settings.py
MEDIA_URL = '/media/'          # 媒体文件访问路径
MEDIA_ROOT = BASE_DIR / 'media'  # 本地存储路径

# 保持使用默认用户模型
# 无需设置 AUTH_USER_MODEL

八、数据迁移
# 生成迁移文件
python manage.py makemigrations

# 执行迁移
python manage.py migrate

# 创建测试用户
python manage.py createsuperuser

九、效果验证
  1. 注册流程
    访问 /users/register → 填写用户名、邮箱、密码、手机号 → 自动创建 User 和 Profile 记录
  2. 资料修改
    登录后访问 /users/profile/edit → 修改头像和简介 → 查看更新后的个人主页
  3. 管理员后台
    访问 /admin → 默认 User 管理界面不变 → 可手动添加 Profile 内联管理(可选)

十、扩展建议
  1. 自动创建Profile
    使用 Django 信号机制:

    # users/signals.py
    from django.db.models.signals import post_save
    from django.dispatch import receiver
    from .models import Profile
    
    @receiver(post_save, sender=User)
    def create_profile(sender, instance, created, **kwargs):
        if created:
            Profile.objects.create(user=instance)
    
    @receiver(post_save, sender=User)
    def save_profile(sender, instance, **kwargs):
        instance.profile.save()
    
  2. 管理员界面增强

    # users/admin.py
    from django.contrib import admin
    from django.contrib.auth.admin import UserAdmin
    from .models import Profile
    
    class ProfileInline(admin.StackedInline):
        model = Profile
    
    class CustomUserAdmin(UserAdmin):
        inlines = [ProfileInline]
    
    admin.site.unregister(User)
    admin.site.register(User, CustomUserAdmin)
    

方案优势

  • 零修改默认用户模型,完全兼容 Django Admin
  • 可灵活添加任意扩展字段
  • 支持渐进式迭代开发
  • 用户系统升级时无需复杂数据迁移
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

Yant224

点滴鼓励,汇成前行星光🌟

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值