今天,我在类似的用例中遇到了完全相同的问题。但是,我不得不处理基于类的视图。基于类的视图允许继承属性和方法,从而更容易以简洁的方式重用代码。
我将通过讨论为用户创建个人资料页面所需的代码来回答您的问题。在此页面上,他们可以更新他们的个人信息。但是,我想在不允许用户更改信息的情况下显示一个电子邮件字段。
是的,我本可以省略电子邮件字段,但我的强迫症不允许这样做。
在下面的示例中,我将表单类与 disabled = True 方法结合使用。此代码在 Django==2.2.7 上测试。
# form class in forms.py
# Alter import User if you have created your own User class with Django default as abstract class.
from .models import User
# from django.contrib.auth.models import User
# Same goes for these forms.
from django.contrib.auth.forms import UserCreationForm, UserChangeForm
class ProfileChangeForm(UserChangeForm):
class Meta(UserCreationForm)
model = User
fields = ['first_name', 'last_name', 'email',]
def __init__(self, *args, **kwargs):
super().__init__(*args, **kwargs)
self.fields['email'].disabled = True
可以看到,指定了所需的用户字段。这些是必须在个人资料页面上显示的字段。如果需要添加其他字段,则必须在 User 类中指定它们,并将属性名称添加到此表单的 Meta 类的字段列表中。
在获得所需的元数据后,调用 __init__ 方法来初始化表单。但是,在此方法中,电子邮件字段参数“已禁用”设置为 True。这样做会改变前端字段的行为,从而导致只读字段即使更改 HTML 代码也无法编辑。参考字段.disabled
为了完成,在下面的示例中可以看到使用表单所需的基于类的视图。
# view class in views.py
from django.contrib import messages
from django.contrib.messages.views import SuccessMessageMixin
from django.contrib.auth.mixins import LoginRequiredMixin
from django.views.generic import TemplateView, UpdateView
from django.utils.translation import gettext_lazy as _
class ProfileView(LoginRequiredMixin, TemplateView):
template_name = 'app_name/profile.html'
model = User
def get_context_data(self, **kwargs):
context = super().get_context_data(**kwargs)
context.update({'user': self.request.user, })
return context
class UserUpdateView(LoginRequiredMixin, SuccesMessageMixin, UpdateView):
template_name = 'app_name/update_profile.html'
model = User
form_class = ProfileChangeForm
success_message = _("Successfully updated your personal information")
def get_success_url(self):
# Please note, one has to specify a get_absolute_url() in the User class
# In my case I return: reverse("app_name:profile")
return self.request.user.get_absolute_url()
def get_object(self, **kwargs):
return self.request.user
def form_valid(self, form):
messages.add_message(self.request, messages.INFO, _("Successfully updated your profile"))
return super().form_valid(form)
ProfileView 类只显示一个 HTML 页面,其中包含有关用户的一些信息。此外,它还包含一个按钮,如果按下该按钮,就会进入由 UserUpdateView 配置的 HTML 页面,即“app_name/update_profile.html”。可以看到,UserUpdateView 拥有两个额外的属性,即“form_class”和“success_message”。
视图知道页面上的每个字段都必须填充来自用户模型的数据。但是,通过引入“form_class”属性,视图不会获得用户字段的默认布局。相反,它被重定向以通过表单类检索字段。这在灵活性方面具有巨大的优势。
通过使用表单类,可以为不同的用户显示具有不同限制的不同字段。如果在模型本身内设置限制,每个用户都会得到相同的待遇。
模板本身并不那么壮观,但可以在下面看到。
# HTML template in 'templates/app_name/update_profile.html'
{% extends "base.html" %}
{% load static %}
{% load crispy_form_tags %}
{% block content %}
<h1>
Update your personal information
<h1/>
<div>
<form class="form-horizontal" method="post" action="{% url 'app_name:update' %}">
{% csrf_token %}
{{ form|crispy }}
<div class="btn-group">
<button type="submit" class="btn btn-primary">
Update
</button>
</div>
</div>
{% endblock %}
可以看出,表单标签包含一个包含视图 URL 路由的操作标签。按下更新按钮后,UserUpdateView 被激活,它会验证是否满足所有条件。如果是,则触发 form_valid 方法并添加成功消息。成功更新数据后,用户将返回到 get_success_url 方法中的指定 URL。
下面可以找到允许视图 URL 路由的代码。
# URL routing for views in urls.py
from django.urls import path
from . import views
app_name = 'app_name'
urlpatterns = [
path('profile/', view=views.ProfileView.as_view(), name='profile'),
path('update/', view=views.UserUpdateView.as_view(), name='update'),
]
你有它。使用表单的基于类的视图的完整实现,因此可以将电子邮件字段更改为只读和禁用。
对于非常详细的示例,我深表歉意。可能有更有效的方法来设计基于类的视图,但这应该可行。当然,我可能对某些事情说错了。我也在学习。如果有人有任何意见或改进,请告诉我!