表单处理流程
- HTTTP GET
- 渲染空表单
Form()
- 渲染带初始值的表单
Form(initial={'key': 'val'})
- 渲染空表单
- HTTP POST
- 提交无效数据
Form(request.POST)
重新渲染表单,并显示错误信息 - 提交有效数据
request.cleaned_data
处理表单,并重定向
- 提交无效数据
FormView 基础类视图
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):
# 当表单验证通过时,调用该方法
# 默认实现是:重定向到 success_url
# This method is called when valid form data has been POSTed.
# It should return an HttpResponse.
form.send_email()
return super().form_valid(form) # 返回一个 HttpResponse: redirect(success_url)
Edit Views(Model forms)
- CreateView
- UpdateView
- DeleteView
只要指定要操作的某一 Model 的 objec, 类视图就可以自动生成 ModelForm, 指定 object 的方法
属性:
model
queryset
方法:.get_queryset()
返回一个 object
- 可以不用为
CreateView
,UpdateView
指定success_url
: 因为它会从 Model 中的.get_absolute_url()
获取 - 这些根据 Model 生成表单的类视图,其
.form_valid()
会自动将表单数据保存到 Model 中 (调用form.save()
)
# models.py
from django.urls import reverse
from django.db import models
class Author(models.Model):
name = models.CharField(max_length=200)
def get_absolute_url(self):
return reverse('author-detail', kwargs={'pk': self.pk})
# views.py
from django.views.generic.edit import CreateView, UpdateView, DeleteView
from django.urls import reverse_lazy
from myapp.models import Author
class AuthorCreate(CreateView):
model = Author
fields = ['name']
class AuthorUpdate(UpdateView):
model = Author
fields = ['name']
class AuthorDelete(DeleteView):
model = Author
success_url = reverse_lazy('author-list')
# urls.py
from django.urls import path
from myapp.views import AuthorCreate, AuthorUpdate, AuthorDelete
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'),
]
总结
属性:
model
fields
form_class
-
success_url
可以从 Model 的.get_absolute_url()
中获取 template_name_suffix
tempalte_name
方法:form_valid()
会自动保存表单数据到数据库,并进行重定向
需要使用 reverse_lazy()
的3中情况:(原因是 此时 URLConf 还未导入)
- 在通用视图中
- 在装饰器中
- 函数为参数提供默认值是
def func(url=reverse_lazy('login'))
从 Python 官方文档的 Python Tutorial 中的函数一章可以知道:函数默认参数的值是在执行到函数定义是确定的,而非在函数调用时确定的
使用属性:form_class
指定自定义的 django.forms.Form
(和 fileds 属性二选一) 模板名由
template_name_suffix` 生成:
- CreateView / UpdateView:
/ _form.html - DeleteView:
/ _comfirm_delete.html
属性
template_name
可以指定渲染的模板
关联当前登录用户 self.request.user
# 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)
from django.views.generic.edit import CreateView
from django.utils.decorators import method_decorator
from myapp.models import Author
@method_decorator(login_reqiured, name='diapatch')
class AuthorCreate(CreateView):
model = Author
fields = ['name']
def form_valid(self, form):
form.instance.created_by = self.request.user # 隐式关联当前用户
return super().form_valid(form)
Ajax
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']
Editing Views