======================= 大爽歌作,made by big shuang =======================
二、拓展CBVs(Class-based views)
一般而言,直接使用原生的Class-based views,能展现的样式和内容是固定的。
为了根据实际情况去定制View,我们需要继承django自带的View并修改。
在修改之前,我们需要先了解下CBVs。
1 Class-based views常用属性和常用方法
model
视图将为其显示数据的模型。(The model that this view will display data for.)
form_class
要实例化的表单类,视图将会根据表单来展示字段。
fields
需要在视图上展示的字段名称组成的列表
补充: form_class 和 fields 必须且只能设置一个。
template_name
由字符串定义的要使用的模板的全名。不定义模板名将引发django.core.exceptions.ImproperlyConfigured
异常。
success_url
成功处理表单时重定向到的URL。
context_object_name
在context
中使用的变量的名称。一般是form
get_context_data()
Returns context data for displaying the object.
The base implementation of this method requires that theself.object
attribute be set by the view (even ifNone
). Be sure to do this if you are using this mixin without one of the built-in views that does so.
It returns a dictionary with these contents:
object
: The object that this view is displaying (self.object
).
context_object_name
:self.object
will also be stored under the name returned byget_context_object_name()
, which defaults to the lowercased version of the model name.
返回用于显示对象的context
数据,返回包含以下内容的词典:
object
:此视图显示的对象(self.object
).
context_object_name
:self.object
还将存储在get_context_object_name()
返回的名称下,该名称默认为模型名称的小写版本。
PS: 需要修改context
数据,可重写此方法
例子如下(出处:adding-extra-context)
class PublisherDetail(DetailView):
model = Publisher
def get_context_data(self, **kwargs):
# Call the base implementation first to get a context
context = super().get_context_data(**kwargs)
# Add in a QuerySet of all the books
context['book_list'] = Book.objects.all()
return context
2 实例
拓展CreateView
欲实现:学生注册时,学生选择年级后注册,自动根据年级按序生成年级子学号
具体来说,一个年级没有学生的话,那么新注册的学生学号就是000001
一个年级有学生的话,取出所有学生里面的最大学号,新注册的学生学号就是最大学号增加1
此时my_app/forms.py
#usr/bin/env python
#-*- coding:utf-8- -*-
from django import forms
from .models import Student
class RegisterForm(forms.ModelForm):
confirm_password = forms.CharField(widget=forms.PasswordInput())
class Meta:
model = Student
fields = ('grade',
'name',
'password',
'confirm_password',
'gender',
'birthday',
'email',
'info')
def clean(self):
cleaned_data = super(RegisterForm, self).clean()
password = cleaned_data.get('password')
confirm_password = cleaned_data.get('confirm_password')
if confirm_password != password:
self.add_error('confirm_password', 'Password does not match.')
my_app/views/register.py
from django.shortcuts import render
from django.http.response import HttpResponse,HttpResponseRedirect
from .models import Student
from django.views.generic import CreateView
from .forms import RegisterForm
class CreateStudentView(CreateView):
model = Student
form_class = RegisterForm
# fields = "__all__"
template_name = "register.html"
success_url = "login"
def post(self, request, *args, **kwargs):
form = self.get_form()
if form.is_valid():
return self.form_valid(form)
else:
return self.form_invalid(form)
def form_valid(self, form):
# 学生注册时选定年级自动生成学号
grade = form.cleaned_data["grade"]
# order_by默认升序排列,number前的负号表示降序排列
student_set = Student.objects.filter(grade=grade).order_by("-number")
if student_set.count() > 0:
last_student = student_set[0]
new_number = str(int(last_student.number) + 1)
for i in range(6 - len(new_number)):
new_number = "0" + new_number
else:
new_number = "000001"
# Create, but don't save the new student instance.
new_student = form.save(commit=False)
# Modify the student
new_student.number = new_number
# Save the new instance.
new_student.save()
# Now, save the many-to-many data for the form.
form.save_m2m()
self.object = new_student
return HttpResponseRedirect(self.get_success_url())
对应urls.py里面的urlpatterns
变量,添加对应的urlpattern
如下
from django.urls import path
from my_app.views import login, register
from my_app import view
urlpatterns = [
path('login/', login.page, name="login"),
path('hello/', view.hello),
path('register', register.CreateStudentView.as_view(),
name="register"),
]
register.html
见 6-1 基于类的视图(Class-based views)介绍
Student
模型见Django自学笔记 4-1 模型(Models)介绍中的示例。
其他代码见本专栏之前博客(实际上本文用不到)