django是mvt模式,其中v就是這個顯示邏輯部分,簡單來講,view函數可以說是接收request,然后處理,返回response的主體函數。
對於一些簡單的邏輯關系,可以用直接用函數模式來進行處理。
def current_datetime(request): now = datetime.datetime.now() html = "<html><body>It is now %s.</body></html>" % now return HttpResponse(html)
如上,很明顯的邏輯,函數接收request為參數,然后隨便做點事情,把內容放到response中返回,剩下的事情django都會幫我們做完。view的中心思想就是這樣,處理顯示部分的邏輯。
當然,當我們寫一些復雜的邏輯的時候,或者說要在一個視圖函數里處理get和post的時候,用這種函數式的表達方法會很復雜,也不容易日后維護和擴展,這個時候django就推薦我們用class來表達來邏輯了。
首先,要通過現象看本質,這個view的主要思想就是處理和返回請求的,無論使用def還是class。
先看一下這兩個在urls.py是怎么樣被綁定的:def是可以直接被引用的,而class是需要引用其as_view的方法, 但是我們可以換個角度看,在設置url映射的時候,不就是綁定了一個函數嘛。
然后在view函數中,他們又有什么不同呢。def函數表達方式,非常直觀,接收request,返回response;而class則沒有那么直觀,要解釋他的邏輯,要從django提供的基本view類講起。
django.views.generic.base.view這個函數就是django所有內置類的爸爸,這個view類有三個方法,dispatch(),http_method_not_allowed(),options()和一個類方法as_view()。
其中,dispatch就是用來判斷request的method,看接下來將這個request派到哪里method的處理函數那里去(如果要用def函數式來做這一步,就需要寫一大堆if request.method == get 之類的判斷),
http_method_not_allowed則是用來過濾掉某些特定method的,options就是用來設置response的一些可選參數。as_view可以理解為class的出口函數。
注意,這個view基類是沒有渲染功能的,也就是說他不能和template進行交互,所以,我們需要在這個基礎去擴展(這里就體現出class的優越性,如果是函數式則需要整體改動,而這里只需要去繼承)
除了上面介紹的view,這個generic view class,還有兩個基本的mixin類,按我個人的理解,view可以單獨拿來用,他本身是完整的,但是mixin不可以,mixin往往只有單個功能,所以需要將mixin作為插件來加到view中。django提供了兩個基本mixin class,一個是ContextMixin,這個mixin就只有一個方法,就是get_context_data,簡單來講,他就是接收一些字典類的參數,然后這些字典傳到template去;第二個是TemplateResponseMixin,其實頁數可以當作只有一個方法,就是render_to_response,沒錯,這個跟shortcuts里面那個一樣,可以理解成返回已經渲染好了的response。
總得來說,這兩個mixin,一個獲取context,一個負責render,就已經可以幫助我們完成很多很多事情了。
來兩個官方的例子
class HomePageView(TemplateView): template_name = "home.html" def get_context_data(self, **kwargs): context = super(HomePageView, self).get_context_data(**kwargs) context['latest_articles'] = Article.objects.all()[:5] return context
這個TemplateView也是django內置的,基類,沒錯,他也是絕大多數內置class的爸爸,當然除了view,他其實就是View,ContextMixin和TemplateResponseMixin的兒子。看一下他的爸爸們,我們很容想到他能干什么,只要為他指定template,然后定義好context的內容,然后就完了,我們就能得到一個渲染好的response了。看源碼可以知道,TemplateView里只有一個方法,就是定義了get(),就沒了,也就是說當請求的方式是get,然后這個請求會被View.dispatch傳到這個get這里,而這個get要做的也不多,第一步,調用ContextMixi.get_context_data,第二步,將第一步得到的context傳到TemplalteResponseMixin.render_to_response,然后就沒了。由此可見,其實我們要做的往往就是去調用django為我們准備好的一些組件
class ArticleCounterRedirectView(RedirectView): permanent = False query_string = True pattern_name = 'article-detail' def get_redirect_url(self, *args, **kwargs): article = get_object_or_404(Article, pk=kwargs['pk']) article.update_counter() return super(ArticleCounterRedirectView, self).get_redirect_url(*args, **kwargs)
這個RedirectView的主要作用就是重定向,注意其中使用到shortcuts的get_object_or_404
