【问题标题】:Django User Update Form and ViewDjango 用户更新表单和视图
【发布时间】:2016-09-24 01:01:35
【问题描述】:

我的 Django/Python 开发之旅还处于起步阶段,经过几个小时/几天的摸索和试错后,我已经能够慢慢弄清楚大多数事情。我现在有一个无法正常工作的常见问题:

如何创建用户个人资料更新视图/表单?

我已经破解了 Stack Overflow 的几个解决方案,但到目前为止我无法弄清楚我做错了什么。这是我使用 Django 1.9 的糟糕尝试的初始版本:

#forms.py
class profileForm(forms.ModelForm):
    class Meta:
        model = User
        fields = ['first_name', 'last_name', 'email']

#views.py
@login_required
def profile(request):
    if request.method == 'POST':
        form = profileForm(data=request.POST, instance=request.user)
        update = form.save(commit=False)
        update.user = request.user
        update.save()
    else:
        form = profileForm(instance=request.user)

    return render(request, 'profile.html', {'form': form})

#urls.py
urlpatterns = [
    url(r'^dashboard/$', views.dashboard, name='dashboard'),
    url(r'^dashboard/profile$', views.profile, name='profile'),
]

#profile.html
<form action="." method="post">
    {% csrf_token %}
    {{ form.as_p }}
    <button type="submit">Update Profile</button>
</form>

因此,我的更新用户配置文件视图的当前行为是不更新 POST 表单中的任何指定字段,但页面确实加载到不同的 URL。例如,配置文件更新表单的 URL 是 /dashboard/profile,它会在提交表单时重定向到 /dashboard。如果我在 Django 管理员中手动添加 email/first_name/last_name,它会在我的表单中正确显示...我只是无法保存更新的数据。

我确实有一个版本的上述代码也给了我用户名错误,我猜这可能已经接近解决方案了?最终我想使用电子邮件地址作为用户名,但是一旦我有一个超简单的工作资料更新表格,我想自己弄清楚。

对于这个愚蠢的问题,我提前道歉,我已经在 Google 上搜索并尝试了其他解决方案,但我要么无法获得相同的初始错误,要么无法获得详细的工作版本。

谢谢大家,祝你白天/夜晚愉快!

编辑:

我也尝试过这个解决方案How to update User object without creating new one?,它也具有相同的行为:不更新 POST 表单中的任何指定字段,但页面确实加载到不同的 URL...这让我更加困惑,也许问题出在我的 urls.py 上?

【问题讨论】:

    标签: python django django-forms django-views django-users


    【解决方案1】:

    我尝试使用抽象用户,它运行良好。首先,我创建了一个名为仪表板的应用程序。然后覆盖默认用户模型。

    现在更新仪表板应用程序 - models.py、urls.py、forms.py 和 views.py

    在 models.py 中

    class User(AbstractUser):    
        middle_name = models.CharField(max_length=50, blank=True, null=True)
        sdl_service_code = models.CharField(choices=SDL_CHOICES, max_length=5)
        account = models.CharField(choices=ACCOUNT_CHOICES, max_length=5)
    

    我通过如下更新设置文件制作了这个新的用户模型(在仪表板应用程序中)django 默认用户模型

    在 settings.py 中

    AUTH_USER_MODEL = 'dashboard.User'
    

    在 urls.py 中

    urlpatterns = [
        path('users', ListUserView.as_view(), name='users'),
        path('users/add/', CreateUserView.as_view(), name='users-add'),
        path('users/<int:pk>/', UpdateUserView.as_view(), name='users-edit'),
        )
    ]
    

    在 forms.py 中

    class UserForm(forms.ModelForm):            
            middle_name = forms.CharField(required=False, max_length=50)
            password = forms.CharField(widget=forms.PasswordInput())
            about_company = form.CharField(required=False, max_length=50)
    
            def __init__(self, *args, **kwargs):
                super(UserForm, self).__init__(*args, **kwargs)
                for field in iter(self.fields):
                    self.fields[field].widget.attrs.update({
                        'class': 'form-control',
                        'placeholder': '{}'.format(field).replace("_", ' ').capitalize(),
    
                    })
    
                self.fields['email'].widget.attrs['placeholder'] = 'abc@xyz.com'
                self.fields['email'].required = True
                self.fields['first_name'].required = True
                self.fields['last_name'].required = True
                self.fields['password'].required = True
    
                if self.instance.pk:
                    self.fields['username'].required = False
                    self.fields['username'].widget.attrs['readonly'] = True
                    self.fields['email'].required = False
                    self.fields['email'].widget.attrs['readonly'] = True
                    self.fields['password'].widget.attrs['readonly'] = True
                    self.fields['password'].required = False
    
            def save(self, *args, **kwargs):
                self.date_joined = date.today()
                super(UserForm, self).save(*args, **kwargs)
                return self
    
            class Meta:
                model = User
                fields = '__all__'
                exclude = ('date_joined',)
    

    在views.py中

    from dashboard.models import User
    from django.views.generic import ListView, DetailView, CreateView, UpdateView
    from dashboard.forms import UserForm
    
    class CreateUserView(CreateView):
        model = User
        template_name = 'dashboard/user_add.html'
        form_class = UserForm
    
        def get_success_url(self):
            return '/users'
    
    class UpdateUserView(UpdateView):
        model = User
        form_class = UserForm
        template_name = 'dashboard/user_add.html'
        success_url = '/users'
    
    class ListUserView(ListView):
        model = User
        template_name = 'dashboard/user_list.html'
    

    【讨论】:

    • 这与我最初的问题无关,3 年前 Daniel Roseman 接受的解决方案直接解决了我的代码中的问题。
    【解决方案2】:

    这里没有特定于用户的内容。你有两个问题:第一个是因为你的网址。您的个人资料视图不以斜线结尾,因此表单的操作是“。”将其发送给父级“/dashboard”,它根本不经过处理代码。

    url(r'/dashboard/profile/$'...)
    

    其次,模型不会更新,因为你没有调用表单的valdation方法。

    if request.method == 'POST':
        form = profileForm(data=request.POST, instance=request.user)
        if form.is_valid():
            form.save()
            return redirect('somewhere')
    

    注意这里没有理由使用 commit=False 的东西;该实例已经是用户。

    【讨论】:

    • 感谢 Daniel 的解释,非常感谢 - urls.py 应该是我检查奇怪提交行为的第一个地方。您的示例似乎缺少冒号 if form.is_valid(): 再次感谢。
    猜你喜欢
    • 2021-12-01
    • 1970-01-01
    • 2011-05-29
    • 2022-10-14
    • 2018-09-29
    • 1970-01-01
    • 2012-12-09
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多