Django 用户更新表单和视图

Django User Update Form and View

我的 Django/Python 开发之旅还很早,经过几次 hours/days 的摸索和 trial/error 之后,我已经能够慢慢弄清楚大多数事情。我现在遇到无法正常工作的常见问题:

如何创建用户配置文件更新View/Form?

我已经破解了 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 搜索并尝试了其他解决方案,但我要么无法得到相同的初始错误,要么无法得到详细的工作版本。

谢谢大家,祝大家生活愉快day/night!

编辑:

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

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

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

其次,模型将不会更新,因为您没有调用表单的验证方法。

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

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

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

立即更新仪表板应用程序 - 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'