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

Django自定义User模型使用UpdateView无法同步更新数据库问题

问题:自定义User模型通过UpdateView更新后数据库未保存修改

问题描述

通过继承AbstractUser实现自定义User模型,使用UpdateView进行更新操作时,点击更新按钮页面刷新后临时显示修改内容,但数据库未实际更新;重新打开页面后,显示的信息仍为修改前的状态。使用Django 4.2.8版本。

相关代码

models.py

class UserManager(models.Manager):
    def New_Requests(self):
        return super.get_queryset().filter(is_seller="I")  # 存在语法错误

class User(AbstractUser):
    nickname = models.CharField(max_length=50,verbose_name="Nick Name",default='User')
    is_seller_status = (
                        ('N','Not accepted'),
                        ('I','Investigate'),
                        ('A','Accepted')
                        )
    is_seller = models.CharField(default='N',max_length=1,choices=is_seller_status,verbose_name='seller')
    user_id = models.UUIDField(default = uuid.uuid4,editable = False,unique=True)
    profile = models.ImageField(upload_to="user_profile",blank=True,null=True)
    admin_reject_reason = models.TextField(default='Not reviewed yet')

views.py

class AccountView(LoginRequiredMixin,UpdateView):
    model = User
    form_class = UserProfileForm
    template_name = "user/profile.html"
    success_url = reverse_lazy("user:profile")

    def get_object(self):
        return User.objects.get(pk = self.request.user.pk)
    
    def get_form_kwargs(self):
        kwargs = super(AccountView, self).get_form_kwargs()
        kwargs['user'] = self.request.user  # Pass 'user' directly to the form
        return kwargs

forms.py

class UserProfileForm(UserChangeForm):
    #User profileform
    def __init__(self,*args, **kwargs):
        user = kwargs.pop('user')
        super(UserProfileForm, self).__init__(*args, **kwargs)

        if not user.is_superuser:
            self.fields['first_name'].disabled = True
            self.fields['last_name'].disabled = True
            #self.fields['email'].help_text = "Change it if it was neccessary"
            self.fields['email'].disabled = True
            self.fields['is_seller'].disabled = True
    
    class Meta:
        #specifing the model and fields
        model = User
        fields = ['profile','nickname','username','email','first_name','last_name',
            'is_seller']

urls.py

app_name = "user"

urlpatterns = [
    ...
    path('profile/',AccountView.as_view(),name='profile'),
    ...
]
urlpatterns += static(settings.MEDIA_URL, document_root=settings.MEDIA_ROOT)

profile.html

{% extends 'user/base.html' %}
{% load static %}
{% load crispy_forms_tags %}
{% block content %}
    <!-- Begin Page Content -->
    <div class="container-fluid">
                    
        <!-- Page Heading -->
        <div class="d-sm-flex align-items-center justify-content-between mb-4">
            <h1 class="h3 mb-0 text-gray-800">Profile</h1>
        </div>
        <div class="col-md-12">
            <div class = "card card-primary">
                <div class="card-header">
                    <h3 class = "card-title mb-0 float-left">User Update</h3>
                </div>
                <div class="card-body">
                    <form method="post" enctype="multipart/form-data">{% csrf_token %}
                        <div class="row">
                            <div class="col-6">
                                {{ form.username|as_crispy_field }}
                            </div>
                            <div class="col-6">
                                {{ form.email|as_crispy_field }}
                            </div>
                            <div class="col-6">
                                {{ form.first_name|as_crispy_field }}
                            </div>
                            <div class="col-6">
                                {{ form.last_name|as_crispy_field }}
                            </div>
                            <div class="col-6">
                                {{ form.is_seller|as_crispy_field }}
                            </div>
                            <div class="col-6">
                                {{ form.profile|as_crispy_field }}
                            </div>         
                        </div>
                        <input class="btn btn-success" type="submit" value="Update">
                        
                    </form>
                </div>
            </div>
        </div>
    </div>                
    <!-- /.container-fluid -->


<!-- End of Main Content -->
{% endblock %}

settings.py

AUTH_USER_MODEL = "user.User"
AUTH_PROFILE_MODULE = "user.User"

原因分析

  1. 表单字段缺失导致隐性验证失败:表单fields包含了nickname,但模板未渲染该字段,提交时缺失该字段值。由于nickname模型字段未设置blank=True,表单触发验证失败但未显示错误提示,导致数据未保存。
  2. UserManager语法错误:New_Requests方法中super.get_queryset()缺少括号,应为super().get_queryset(),虽不直接影响UpdateView,但属于代码隐患。
  3. 用户实例缓存问题:即使数据保存成功,request.user可能处于Django缓存中,重定向后显示缓存数据而非最新数据库数据。

解决方案

1. 补充模板中缺失的表单字段

在profile.html的表单中添加nickname字段的渲染:

<div class="col-6">
    {{ form.nickname|as_crispy_field }}
</div>

2. 修复UserManager语法错误

修改models.py中的New_Requests方法:

def New_Requests(self):
    return super().get_queryset().filter(is_seller="I")

3. 重写form_valid方法确保保存并刷新缓存

在views.py的AccountView中添加form_valid方法:

def form_valid(self, form):
    # 保存表单数据到数据库
    self.object = form.save()
    # 刷新request.user实例,更新缓存
    self.request.user.refresh_from_db()
    return super().form_valid(form)

4. 添加表单错误提示(可选)

在模板表单顶部添加错误提示,方便排查验证问题:

{% if form.errors %}
    <div class="alert alert-danger mb-3">
        {{ form.errors }}
    </div>
{% endif %}

验证步骤

修改完成后重启服务:

  1. 修改用户信息(如用户名、昵称)并提交
  2. 直接查看数据库中对应的User记录,确认是否更新
  3. 重新打开页面或刷新,确认显示最新数据

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.07.04 17:30:00