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

Django中使用Form而非ModelForm填充表单实现资料编辑

解决方案:用Form实现用户资料填充与编辑

因为你使用的是forms.Form而非ModelForm,无法通过instance参数绑定模型实例,所以需要通过**initial参数填充现有用户数据**,并在表单验证通过后手动更新用户模型。下面是具体修改步骤:

1. 调整CustomerForm适配编辑场景

编辑资料时用户可能不需要修改密码,先把密码字段设为非必填,同时调整验证逻辑,只有当用户输入密码时才校验一致性:

# forms.py
from django import forms
from django.contrib.auth.validators import validate_username
from django.core.validators import validate_email
from django.core.exceptions import ValidationError

class CustomerForm(forms.Form):
    username = forms.CharField(label='Desired Username', max_length=150, validators=[validate_username])
    first_name = forms.CharField(label='First Name', max_length=150)
    last_name = forms.CharField(label='Last Name', max_length=150)
    email = forms.EmailField(label='Your Email', validators=[validate_email])
    # 编辑时密码可选,设为非必填
    password1 = forms.CharField(label='Enter Password', widget=forms.PasswordInput, min_length=8, required=False)
    password2 = forms.CharField(label='Retype Password', widget=forms.PasswordInput, min_length=8, required=False)

    def clean(self):
        cleaned_data = super().clean()
        password1 = cleaned_data.get("password1")
        password2 = cleaned_data.get("password2")

        # 只有当两个密码字段都有值时才校验匹配
        if password1 or password2:
            if password1 != password2:
                raise ValidationError("Passwords do not match")
        return cleaned_data

2. 修改edit_profile视图,用initial填充表单

GET请求时,把当前用户的字段值传入表单的initial参数来填充表单;POST请求时,验证表单后手动更新User实例:

# views.py
from django.shortcuts import render, redirect
from django.contrib.auth import login, get_user_model
from django.http import HttpResponse
from .forms import CustomerForm

User = get_user_model()

"""Function for editing profile."""
def edit_profile(request):
    # 直接用request.user获取当前登录用户,比session更安全
    profile = request.user

    if request.method == 'POST':
        form = CustomerForm(request.POST)
        if form.is_valid():
            # 手动更新用户字段
            profile.username = form.cleaned_data['username']
            profile.first_name = form.cleaned_data['first_name']
            profile.last_name = form.cleaned_data['last_name']
            profile.email = form.cleaned_data['email']
            # 如果用户输入了密码,才更新密码
            if form.cleaned_data['password1']:
                profile.set_password(form.cleaned_data['password1'])
            profile.save()
            return redirect('../book/')
        else:
            return render(request, 'edit.html', {'form': form})
    # GET请求时,用initial填充现有用户数据
    initial_data = {
        'username': profile.username,
        'first_name': profile.first_name,
        'last_name': profile.last_name,
        'email': profile.email,
        # 密码字段留空,避免显示明文或哈希值
    }
    form = CustomerForm(initial=initial_data)
    return render(request, 'edit.html', {'form': form})

3. 优化原代码的小问题

  • 原sign_up视图里用request.session['normal_username']没必要,登录后直接用request.user即可
  • 异常处理别用宽泛的Exception,可以捕获具体异常比如IntegrityError(用户名/邮箱重复),给用户更明确的提示:
# 优化后的sign_up视图
from django.db import IntegrityError

"""Function for sign up."""
def sign_up(request):
    if request.method == 'POST':
        form = CustomerForm(request.POST)
        if form.is_valid():
            try:
                user = User.objects.create_user(
                    username=form.cleaned_data['username'],
                    email=form.cleaned_data['email'],
                    password=form.cleaned_data['password1']
                )
                user.first_name = form.cleaned_data['first_name']
                user.last_name = form.cleaned_data['last_name']
                user.save()
                login(request, user)
                return redirect('../book/')
            except IntegrityError:
                form.add_error('username', 'This username is already taken.')
                return render(request, 'sign_up.html', {'form': form})
        return render(request, 'sign_up.html', {'form': form})
    return render(request, 'sign_up.html', {'form': CustomerForm()})

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.08.17 05:15:27