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'
我的 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'