← 内置CBV视图 | 总目录 | 使用mixins →
表单处理通常有3种情况:
给出一个简单的表单:
#forms.py
from django import forms
class ContactForm(forms.Form):
name = forms.CharField()
message = forms.CharField(widget=forms.Textarea)
def send_email(self):
# send email using the self.cleaned_data dictionary
pass
可以使用以下方法构建FormView视图:
# views.py
from myapp.forms import ContactForm
from django.views.generic.edit import FormView
class ContactView(FormView):
template_name = 'contact.html'
form_class = ContactForm
success_url = '/thanks/'
def form_valid(self, form):
# This method is called when valid form data has been POSTed.
# It should return an HttpResponse.
form.send_email()
return super().form_valid(form)
注意:
1 . FormView继承自 TemplateResponseMixin,所以可以在这里使用 template_name 。
2.form_valid()的默认实现就是简单重定向到success_url。
译者注
html中这么使用:
<form action="{% url 'polls:cbv_form_view' %}" method="POST" enctype="multipart/form-data">
{% csrf_token %}
{{ form.name.label }}{{ form.name }}<br>
{{ form.message.label }}{{ form.message }}<br>
<input type="submit" value="提交">
form>
通用视图和model一起工作很屌。这些通用视图将自动创建一个ModelForm,只要它们可以确定要使用的模型类,可以通过以下三种方式:
ModelForm视图中form_valid()的实现是自动保存模型。如果您有任何特殊要求,可以覆盖它; 见下面的例子。
您甚至不需要为 CreateView 或 UpdateView 提供success_url - 如果get_absolute_url()可用,它们将在模型对象上使用此方法。
如果要使用自定义ModelForm(例如添加额外验证),只需在视图上设置 form_class即可 。
注意
指定自定义表单类时,您仍必须指定模型,即使 form_class 可能是个 ModelForm。
首先我们需要添加get_absolute_url()
到我们的 Author类:
#models.py
from django.db import models
from django.urls import reverse
class Author(models.Model):
name = models.CharField(max_length=200)
def get_absolute_url(self):
#译者注:这里author-detail应该是这种形式-> yourapp:author-detail 否则反向解析会报错
return reverse('author-detail', kwargs={'pk': self.pk})
请注意我们如何在这里配置CBV的通用视图,我们自己不必写任何逻辑:
#views.py
from django.urls import reverse_lazy
from django.views.generic.edit import CreateView, DeleteView, UpdateView
from myapp.models import Author
class AuthorCreate(CreateView):
model = Author
fields = ['name']
class AuthorUpdate(UpdateView):
model = Author
fields = ['name']
class AuthorDelete(DeleteView):
model = Author
#译者注:这里author-list应该是这种形式-> yourapp:author-list 否则反向解析会报错
success_url = reverse_lazy('author-list')
注意
我们必须在这里使用 reverse_lazy(),而不是 reverse(),因为在导入文件时未加载URL。
fields属性的工作方式与ModelForm内部Meta类上的fields属性相同。除非您以另一种方式(通过指定form_class)定义表单类,否则该属性是必需的,如果不是,则视图将引发异常 ImproperlyConfigured。
如果同时指定 fields 和 form_class 属性, 则会引发异常ImproperlyConfigured。
最后,我们将这些新视图关联到URLconf:
# urls.py
from django.urls import path
from myapp.views import AuthorCreate, AuthorDelete, AuthorUpdate
urlpatterns = [
# ...
path('author/add/', AuthorCreate.as_view(), name='author-add'),
path('author//' , AuthorUpdate.as_view(), name='author-update'),
path('author//delete/' , AuthorDelete.as_view(), name='author-delete'),
]
注意
这些视图继承自 SingleObjectTemplateResponseMixin 它使用 template_name_suffix 构建 template_name 基于模型。
在这个例子中:
myapp/author_form.html
(可以改变模板名,可以 在视图类中设置 template_name或 template_name_suffix)myapp/author_confirm_delete.html
(译者注:不可以改变模板名,只能是模型_confirm_delete.html
)要跟踪用户使用CreateView创建的对象,可以使用自定义ModelForm来执行此操作。首先,将外键关系添加到模型中:
# models.py
from django.contrib.auth.models import User
from django.db import models
class Author(models.Model):
name = models.CharField(max_length=200)
created_by = models.ForeignKey(User, on_delete=models.CASCADE)
# ...
在视图中,确保您没有在要fields列表中包含created_by字段,并覆盖 form_valid()
以添加用户:
# views.py
from django.views.generic.edit import CreateView
from myapp.models import Author
class AuthorCreate(CreateView):
model = Author
fields = ['name']
def form_valid(self, form):
form.instance.created_by = self.request.user
return super().form_valid(form)
请注意,您需要使用装饰器 login_required() 来 装饰此视图,或者在form_valid()中处理未经授权的用户 。
这是一个简单的示例,展示了如何实现适用于AJAX请求以及“普通”POST请求的表单:
from django.http import JsonResponse
from django.views.generic.edit import CreateView
from myapp.models import Author
class AjaxableResponseMixin:
"""
Mixin to add AJAX support to a form.
Must be used with an object-based FormView (e.g. CreateView)
"""
def form_invalid(self, form):
response = super().form_invalid(form)
if self.request.is_ajax():
return JsonResponse(form.errors, status=400)
else:
return response
def form_valid(self, form):
# We make sure to call the parent's form_valid() method because
# it might do some processing (in the case of CreateView, it will
# call form.save() for example).
response = super().form_valid(form)
if self.request.is_ajax():
data = {
'pk': self.object.pk,
}
return JsonResponse(data)
else:
return response
class AuthorCreate(AjaxableResponseMixin, CreateView):
model = Author
fields = ['name']