今天,我在一个类似的用例中遇到了完全相同的问题。然而,我必须处理基于类的视图。基于类的视图允许继承属性和方法,从而更容易以简洁的方式重用代码。
我将通过讨论为用户创建个人资料页面所需的代码来回答您的问题。在这个页面上,他们可以更新他们的个人信息。但是,我想在不允许用户更改信息的情况下显示电子邮件字段。
是的,我本可以省略电子邮件字段,但我的强迫症不允许这样做。
在下面的例子中,我使用了一个form类和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__方法初始化表单。然而,在这个方法中,email字段参数“disabled”被设置为True。通过这样做,前端字段的行为被改变,导致一个只读字段,即使改变HTML代码也不能编辑。参考Field.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'。
视图知道页面上的每个字段都必须用来自User模型的数据填充。然而,通过引入'form_class'属性,视图不会得到User字段的默认布局。相反,它被重定向为通过表单类检索字段。这在灵活性方面有巨大的优势。
通过使用表单类,可以为不同的用户显示具有不同限制的不同字段。如果在模型内部设置限制,每个用户都会得到相同的待遇。
模板本身不是那么壮观,但可以在下面看到。
# 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路由。
在按下Update按钮后,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'),
]
你知道了。一个使用form的基于类的视图的完整实现,因此可以将电子邮件字段更改为只读和禁用。
我为这个极其详细的例子道歉。可能有更有效的方法来设计基于类的视图,但这应该是可行的。当然,有些话我可能说错了。我也还在学习。如果任何人有任何意见或改进,让我知道!