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

Django中Profile Model无法保存更新请求助

修复用户Profile更新功能的问题

我看了你的代码,发现几个关键问题导致更新功能失效,下面一步步帮你解决:

1. 信号连接错误(models.py)

你的post_save信号错误地连接到了userr这个User实例,而不是User模型类,这会导致信号永远不会触发。另外,创建Profile时的关联参数也有误,应该直接绑定user实例而非user_id。

修改后的models.py:

from django.contrib.auth.models import User
from django.db.models.signals import post_save
from django.dispatch import receiver

class Profile(models.Model):
    user = models.OneToOneField(User, null=True, blank=True, on_delete=models.CASCADE)
    nama = models.CharField(max_length=30, blank=True)
    nik = models.CharField(max_length=30, blank=True)
    email = models.EmailField(max_length=75, blank=True)
    nomor_hp = models.TextField(max_length=15, blank=True)
    
    def __str__(self):
        return self.user.username  # 原代码返回User实例会报错,改为返回用户名字符串

@receiver(post_save, sender=User)
def create_profile(sender, instance, created, **kwargs):
    """为每个新创建的User自动生成Profile"""
    if created:
        Profile.objects.create(user=instance)  # 直接关联User实例

2. 表单定义错误(forms.py)

你没有给User相关的表单定义类名,而且误用了PasswordChangeForm——这个表单专门用于修改密码,无法处理email、username的更新。应该自定义一个User模型表单:

修改后的forms.py:

from django import forms
from django.contrib.auth.models import User
from .models import Profile

class UserUpdateForm(forms.ModelForm):
    class Meta:
        model = User
        fields = ('email', 'username')  # 密码单独用PasswordChangeForm处理,不要放这里
        widgets = {
            'email' : forms.EmailInput(attrs={'class' : 'form-control form-control-user', 'id' : 'exampleInputEmail', 'placeholder' : 'Email Address'}),
            'username': forms.TextInput(attrs={'class' : 'form-control form-control-user', 'id' : 'exampleFirstName', 'placeholder' : 'Username'})
        }

class ProfileForm(forms.ModelForm):
    class Meta:
        model = Profile
        fields = ['nama', 'nik', 'email', 'nomor_hp']
        widgets = {
            'nama': forms.TextInput(attrs={ 'id' : 'exampleFirstName', 'placeholder' : 'Name'}),
            'nik' : forms.NumberInput(attrs={'id' : 'exampleLastName', 'placeholder' : 'Nomor Identitas Penduduk'}),
            'email' : forms.EmailInput(attrs={'id' : 'exampleInputEmail', 'placeholder' : 'Email Address'}),
            'nomor_hp' : forms.NumberInput(attrs={'size':'4', 'maxlength':'12', 'class':'phone', 'placeholder' : 'Nomor Handphone'}),
        }

注意:删掉了widget里的name属性,Django会自动生成正确的name值,手动设置可能导致表单数据无法正确绑定。

3. 视图逻辑错误(views.py)

  • 错误地用PasswordChangeForm处理用户信息更新,应该替换为上面的UserUpdateForm
  • Profile实例不应该按pk获取,而是通过User实例的反向关联(user.profile)获取,因为Profile的id和User的id不一定一致
  • 表单处理逻辑要包裹在if request.method == 'POST'里,避免GET请求时触发不必要的验证
  • 两个表单需要同时验证,分开的if会导致只处理第一个有效的表单
  • 建议添加权限校验,确保用户只能修改自己的Profile

修改后的views.py:

from django.shortcuts import render, get_object_or_404, redirect
from django.contrib.auth.models import User
from .forms import UserUpdateForm, ProfileForm
from .models import Profile

def post_update(request, pk):
    # 获取要修改的User实例,不存在则返回404
    user = get_object_or_404(User, pk=pk)
    
    # 权限校验:当前用户只能修改自己的信息(可根据需求调整)
    if request.user != user:
        return redirect('pengurusan:index')  # 跳转到首页或无权限页面
    
    # 获取对应Profile实例,不存在则自动创建(兼容信号未触发的情况)
    profile, created = Profile.objects.get_or_create(user=user)
    
    if request.method == 'POST':
        user_form = UserUpdateForm(request.POST, instance=user)
        profile_form = ProfileForm(request.POST, instance=profile)
        
        if user_form.is_valid() and profile_form.is_valid():
            user_form.save()
            profile_form.save()
            return redirect('pengurusan:index')  # 使用命名URL更可靠
    else:
        # GET请求时,用现有实例初始化表单,显示当前数据
        user_form = UserUpdateForm(instance=user)
        profile_form = ProfileForm(instance=profile)
    
    context={ 
        "user_form" : user_form, 
        "profile_form" : profile_form, 
        "user" : user, 
        "profile" : profile, 
    }
    return render(request, 'pengurusan/update-form.html', context)

额外注意事项

  • 模板中要确保表单标签包含enctype="multipart/form-data"(如果后续给Profile添加头像等文件字段的话)
  • 测试前先确认用户对应的Profile已创建(可以通过后台或get_or_create逻辑保证)
  • 密码修改建议单独做一个视图,使用PasswordChangeForm,不要和基础信息更新混在一起

这样修改后,你的Profile更新功能应该就能正常工作了。

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.05.08 17:12:27