1. 程式人生 > >Django框架視圖類

Django框架視圖類

self set ora pageview 繼承 第一條 apol url class

類視圖

在寫視圖的時候,Django除了使用函數作為視圖,也可以使用類作為視圖.使用類視圖可以使用類的一些特性,比如繼承等.

View

django.views.generic.base.View是主要的類視圖,所有的類視圖都是繼承自他.如果我們寫自己的類視圖,也可以繼承自他.然後再根據當前請求的method,來實現不同的方法.比如這個視圖只能使用get的方式來請求,那麽就可以在這個類中定義get(self,request,*args,**kwargs)方法.以此類推,如果只需要實現post方法,那麽就只需要在類中實現post(self,request,*args,**kwargs).
示例代碼如下:

from django.views import View
class BookDetailView(View):
    def get(self,request,*args,**kwargs):
        return render(request,'detail.html')

類視圖寫完後,還應該在urls.py中進行映射,映射的時候就需要調用View的類方法as_view()來進行轉換.
示例代碼如下:

urlpatterns = [        
    path("book_detail/<book_id>/",views.BookDetailView.as_view(),name='detail')
]

除了get方法,View還支持以下方法[‘get‘,‘post‘,‘put‘,‘patch‘,‘delete‘,‘head‘,‘options‘,‘trace‘].

如果用戶訪問了View中沒有定義的方法.比如你的類視圖只支持get方法,而出現了post方法,那麽就會把這個請求轉發給http_method_not_allowed(request,*args,**kwargs).
示例代碼如下:

class AddBookView(View):
    def post(self,request,*args,**kwargs):
        return HttpResponse("書籍添加成功!")

    def http_method_not_allowed(self, request, *args, **kwargs):
        return HttpResponse("您當前采用的method是:%s,本視圖只支持使用post請求!" % request.method)

urls.py中的映射如下:

path("addbook/",views.AddBookView.as_view(),name='add_book')

如果你在瀏覽器中訪問addbook/,因為瀏覽器訪問采用的是get方法,而addbook只支持post方法,因此以上視圖會返回您當前采用的method是:GET,本視圖只支持使用post請求!
其實不管是get請求還是post請求,都會走dispatch(request,*args,**kwargs)方法,所以如果實現這個方法,將能夠對所有請求都處理到.

TemplateView

django.views.generic.base.TemplateView,這個類視圖是專門用來返回模版的.在這個類中,有兩個屬性是經常需要用到的,一個是template_name,這個屬性是用來存儲模版的路徑,TemplateView會自動的渲染這個變量指向的模版.另外一個是get_context_data,這個方法是用來返回上下文數據的,也就是在給模版傳的參數的.
示例代碼如下:

from django.views.generic.base import TemplateView
class HomePageView(TemplateView):
    template_name = "home.html"
    def get_context_data(self, **kwargs):
        context = super().get_context_data(**kwargs)
        context['username'] = "Apollo"
        return context

在urls.py中的映射代碼如下:

from django.urls import path
from myapp.views import HomePageView
urlpatterns = [
    path('', HomePageView.as_view(), name='home'),
]

如果在模版中不需要傳遞任何參數,那麽可以直接只在urls.py中使用TemplateView來渲染模版.
示例代碼如下:

from django.urls import path
from django.views.generic import TemplateView

urlpatterns = [
    path('about/', TemplateView.as_view(template_name="about.html")),
]

ListView

在網站開發中,經常會出現需要列出某個表中的一些數據作為列表展示出來.比如文章列表,圖書列表等等.在Django中可以使用ListView來幫我們快速實現這種需求.
示例代碼如下:

class ArticleListView(ListView):
    model = Article
    template_name = 'article_list.html'
    paginate_by = 10
    context_object_name = 'articles'
    ordering = 'create_time'
    page_kwarg = 'page'

    def get_context_data(self, **kwargs):
        context = super(ArticleListView, self).get_context_data(**kwargs)
        print(context)
        return context

    def get_queryset(self):
        return Article.objects.filter(id__lte=89)

對以上代碼進行解釋:
1.首先ArticleListView是繼承自ListView。
2.model:重寫model類屬性,指定這個列表是給哪個模型的。
3.template_name:指定這個列表的模板。
4.paginate_by:指定這個列表一頁中展示多少條數據。
5.context_object_name:指定這個列表模型在模板中的參數名稱。
6.ordering:指定這個列表的排序方式。
7.page_kwarg:獲取第幾頁的數據的參數名稱。默認是page。
8.get_context_data:獲取上下文的數據。
9.get_queryset:如果你提取數據的時候,並不是要把所有數據都返回,那麽你可以重寫這個方法。將一些不需要展示的數據給過濾掉。

Paginator和Page類

Paginator和Page類都是用來做分頁的.他們在Django中的路徑為django.core.paginator.Paginator和django.core.paginator.Page.
以下對這兩個類的常用屬性和方法做解釋:

Paginator常用屬性和方法:

1.count:總共有多少條數據。
2.num_pages:總共有多少頁。
3.page_range:頁面的區間.比如有三頁,那麽就range(1,4).

Page常用屬性和方法

1.has_next:是否還有下一頁。
2.has_previous:是否還有上一頁。
3.next_page_number:下一頁的頁碼。
4.previous_page_number:上一頁的頁碼。
5.number:當前頁。
6.start_index:當前這一頁的第一條數據的索引值。
7.end_index:當前這一頁的最後一條數據的索引值。

給類視圖添加裝飾器

在開發中,有時候需要給一些視圖添加裝飾器.如果用函數視圖那麽非常簡單,只要在函數的上面寫上裝飾器就可以了.但是如果想要給類添加裝飾器,那麽可以通過以下兩種方式來實現:

裝飾dispatch方法:

from django.utils.decorators import method_decorator
def login_required(func):
    def wrapper(request,*args,**kwargs):
        if request.GET.get("username"):
            return func(request,*args,**kwargs)
        else:
            return redirect(reverse('index'))
    return wrapper

class IndexView(View):
    def get(self,request,*args,**kwargs):
        return HttpResponse("index")

    @method_decorator(login_required)
    def dispatch(self, request, *args, **kwargs):
        super(IndexView, self).dispatch(request,*args,**kwargs)

直接裝飾在整個類上

from django.utils.decorators import method_decorator
def login_required(func):
    def wrapper(request,*args,**kwargs):
        if request.GET.get("username"):
            return func(request,*args,**kwargs)
        else:
            return redirect(reverse('login'))
    return wrapper


@method_decorator(login_required,name='dispatch')
class IndexView(View):
    def get(self,request,*args,**kwargs):
        return HttpResponse("index")

    def dispatch(self, request, *args, **kwargs):
        super(IndexView, self).dispatch(request,*args,**kwargs)

Django框架視圖類