Django自學筆記 6-2 拓展CBVs(Class-based views)

————總目錄——前言——框架版本————

======================= 大爽歌作,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 the self.object attribute be set by the view (even if None). 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 by get_context_object_name(), which defaults to the lowercased version of the model name.

返回用於顯示對象的context數據,返回包含以下內容的詞典:
object:此視圖顯示的對象(self.object).
context_object_nameself.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.html6-1 基於類的視圖(Class-based views)介紹
Student模型見Django自學筆記 4-1 模型(Models)介紹中的示例。
其他代碼見本專欄之前博客(實際上本文用不到)

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章