Django重溫2

1 ..類視圖

1.1 類視圖引入

以函數(shù)的方式定義的視圖稱為函數(shù)視圖灶似,函數(shù)視圖便于理解浸剩。但是遇到一個(gè)視圖對(duì)應(yīng)的路徑提供了多種不同HTTP請求方式的支持時(shí)伏嗜,便需要在一個(gè)函數(shù)中編寫不同的業(yè)務(wù)邏輯刻获,代碼可讀性與復(fù)用性都不佳坪创。

def register(request):

? ? """處理注冊"""


? ? # 獲取請求方法塌鸯,判斷是GET/POST請求

? ? if request.method == 'GET':

? ? ? ? # 處理GET請求侍瑟,返回注冊頁面

? ? ? ? return render(request, 'register.html')

? ? else:

? ? ? ? # 處理POST請求,實(shí)現(xiàn)注冊邏輯

? ? ? ? return HttpResponse('這里實(shí)現(xiàn)注冊邏輯')

在Django中也可以使用類來定義一個(gè)視圖丙猬,稱為類視圖涨颜。

使用類視圖可以將視圖對(duì)應(yīng)的不同請求方式以類中的不同方法來區(qū)別定義。如下所示

from django.views.generic import View

class RegisterView(View):

? ? """類視圖:處理注冊"""


? ? def get(self, request):

? ? ? ? """處理GET請求茧球,返回注冊頁面"""

? ? ? ? return render(request, 'register.html')


? ? def post(self, request):

? ? ? ? """處理POST請求庭瑰,實(shí)現(xiàn)注冊邏輯"""

? ? ? ? return HttpResponse('這里實(shí)現(xiàn)注冊邏輯')

類視圖的好處:

代碼可讀性好

類視圖相對(duì)于函數(shù)視圖有更高的復(fù)用性, 如果其他地方需要用到某個(gè)類視圖的某個(gè)特定邏輯抢埋,直接繼承該類視圖即可


1.2 類視圖使用

定義類視圖需要繼承自Django提供的父類View弹灭,可使用from django.views.generic import View或者from django.views.generic.base import View 導(dǎo)入,定義方式如上所示揪垄。

配置路由時(shí)穷吮,使用類視圖的as_view()方法來添加。

urlpatterns = [

? ? # 視圖函數(shù):注冊

? ? # url(r'^register/$', views.register, name='register'),

? ? # 類視圖:注冊

? ? url(r'^register/$', views.RegisterView.as_view(), name='register'),

]

1.3 類視圖原理

? ? @classonlymethod

? ? def as_view(cls, **initkwargs):

? ? ? ? """

? ? ? ? Main entry point for a request-response process.

? ? ? ? """

? ? ? ? ...省略代碼...


? ? ? ? def view(request, *args, **kwargs):

? ? ? ? ? ? self = cls(**initkwargs)

? ? ? ? ? ? if hasattr(self, 'get') and not hasattr(self, 'head'):

? ? ? ? ? ? ? ? self.head = self.get

? ? ? ? ? ? self.request = request

? ? ? ? ? ? self.args = args

? ? ? ? ? ? self.kwargs = kwargs

? ? ? ? ? ? # 調(diào)用dispatch方法饥努,按照不同請求方式調(diào)用不同請求方法

? ? ? ? ? ? return self.dispatch(request, *args, **kwargs)


? ? ? ? ...省略代碼...


? ? ? ? # 返回真正的函數(shù)視圖

? ? ? ? return view



? ? def dispatch(self, request, *args, **kwargs):

? ? ? ? # Try to dispatch to the right method; if a method doesn't exist,

? ? ? ? # defer to the error handler. Also defer to the error handler if the

? ? ? ? # request method isn't on the approved list.

? ? ? ? if request.method.lower() in self.http_method_names:

? ? ? ? ? ? handler = getattr(self, request.method.lower(), self.http_method_not_allowed)

? ? ? ? else:

? ? ? ? ? ? handler = self.http_method_not_allowed

? ? ? ? return handler(request, *args, **kwargs)

1.4 類視圖使用裝飾器

為類視圖添加裝飾器捡鱼,可以使用三種方法。

為了理解方便酷愧,我們先來定義一個(gè)為函數(shù)視圖準(zhǔn)備的裝飾器(在設(shè)計(jì)裝飾器時(shí)基本都以函數(shù)視圖作為考慮的被裝飾對(duì)象)驾诈,及一個(gè)要被裝飾的類視圖。

def my_decorator(func):

? ? def wrapper(request, *args, **kwargs):

? ? ? ? print('自定義裝飾器被調(diào)用了')

? ? ? ? print('請求路徑%s' % request.path)

? ? ? ? return func(request, *args, **kwargs)

? ? return wrapper


class DemoView(View):

? ? def get(self, request):

? ? ? ? print('get方法')

? ? ? ? return HttpResponse('ok')


? ? def post(self, request):

? ? ? ? print('post方法')

? ? ? ? return HttpResponse('ok')


1.4.1 在URL配置中裝飾

urlpatterns = [

? ? url(r'^demo/$', my_decorate(DemoView.as_view()))

]

在類視圖中使用為函數(shù)視圖準(zhǔn)備的裝飾器時(shí)溶浴,不能直接添加裝飾器翘鸭,需要使用method_decorator將其轉(zhuǎn)換為適用于類視圖方法的裝飾器。


from django.utils.decorators import method_decorator


# 為全部請求方法添加裝飾器

class DemoView(View):


? ? @method_decorator(my_decorator)

? ? def dispatch(self, *args, **kwargs):

? ? ? ? return super().dispatch(*args, **kwargs)


? ? def get(self, request):

? ? ? ? print('get方法')

? ? ? ? return HttpResponse('ok')


? ? def post(self, request):

? ? ? ? print('post方法')

? ? ? ? return HttpResponse('ok')



# 為特定請求方法添加裝飾器

class DemoView(View):


? ? @method_decorator(my_decorator)

? ? def get(self, request):

? ? ? ? print('get方法')

? ? ? ? return HttpResponse('ok')


? ? def post(self, request):

? ? ? ? print('post方法')

? ? ? ? return HttpResponse('ok')

method_decorator裝飾器還支持使用name參數(shù)指明被裝飾的方法

# 為全部請求方法添加裝飾器

@method_decorator(my_decorator, name='dispatch')

class DemoView(View):

? ? def get(self, request):

? ? ? ? print('get方法')

? ? ? ? return HttpResponse('ok')


? ? def post(self, request):

? ? ? ? print('post方法')

? ? ? ? return HttpResponse('ok')



# 為特定請求方法添加裝飾器

@method_decorator(my_decorator, name='get')

class DemoView(View):

? ? def get(self, request):

? ? ? ? print('get方法')

? ? ? ? return HttpResponse('ok')


? ? def post(self, request):

? ? ? ? print('post方法')

? ? ? ? return HttpResponse('ok')

為什么需要使用method_decorator???

為函數(shù)視圖準(zhǔn)備的裝飾器戳葵,其被調(diào)用時(shí)就乓,第一個(gè)參數(shù)用于接收request對(duì)象

def my_decorate(func):

? ? def wrapper(request, *args, **kwargs):? # 第一個(gè)參數(shù)request對(duì)象

? ? ? ? ...代碼省略...

? ? ? ? return func(request, *args, **kwargs)

? ? return wrapper

而類視圖中請求方法被調(diào)用時(shí),傳入的第一個(gè)參數(shù)不是request對(duì)象,而是self 視圖對(duì)象本身生蚁,第二個(gè)位置參數(shù)才是request對(duì)象

class DemoView(View):

? ? def dispatch(self, request, *args, **kwargs):

? ? ? ? ...代碼省略...


? ? def get(self, request):

? ? ? ? ...代碼省略...

所以如果直接將用于函數(shù)視圖的裝飾器裝飾類視圖方法噩翠,會(huì)導(dǎo)致參數(shù)傳遞出現(xiàn)問題。

method_decorator的作用是為函數(shù)視圖裝飾器補(bǔ)充第一個(gè)self參數(shù)邦投,以適配類視圖方法伤锚。

如果將裝飾器本身改為可以適配類視圖方法的,類似如下志衣,則無需再使用method_decorator屯援。

def my_decorator(func):

? ? def wrapper(self, request, *args, **kwargs):? # 此處增加了self

? ? ? ? print('自定義裝飾器被調(diào)用了')

? ? ? ? print('請求路徑%s' % request.path)

? ? ? ? return func(self, request, *args, **kwargs)? # 此處增加了self

? ? return wrapper

2.中間件

目的: 知道中間件中的代碼和視圖函數(shù)中的代碼, 執(zhí)行的時(shí)間順序

使用流程:

1, 創(chuàng)建文件,定義中間件方法; booktest/my_middleware.py

defsimple_middleware(get_response):

# 此處編寫的代碼僅在Django第一次配置和初始化的時(shí)候執(zhí)行一次。

print("1, init")

defmiddleware(request):

# 此處編寫的代碼會(huì)在每個(gè)請求處理視圖前被調(diào)用念脯。

print("1, before_request")

?

response=get_response(request)

?

# 此處編寫的代碼會(huì)在每個(gè)請求處理視圖之后被調(diào)用狞洋。

print("1, after_request")

?

returnresponse

?

returnmiddleware

2,注冊中間件列表; settings.py

MIDDLEWARE= [

?? ...

'booktest.my_middleware.simple_middleware',

]

調(diào)用流程圖解


最后編輯于
?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請聯(lián)系作者
  • 序言:七十年代末,一起剝皮案震驚了整個(gè)濱河市绿店,隨后出現(xiàn)的幾起案子吉懊,更是在濱河造成了極大的恐慌,老刑警劉巖假勿,帶你破解...
    沈念sama閱讀 210,914評(píng)論 6 490
  • 序言:濱河連續(xù)發(fā)生了三起死亡事件借嗽,死亡現(xiàn)場離奇詭異,居然都是意外死亡转培,警方通過查閱死者的電腦和手機(jī)恶导,發(fā)現(xiàn)死者居然都...
    沈念sama閱讀 89,935評(píng)論 2 383
  • 文/潘曉璐 我一進(jìn)店門,熙熙樓的掌柜王于貴愁眉苦臉地迎上來浸须,“玉大人惨寿,你說我怎么就攤上這事∮鸾洌” “怎么了?”我有些...
    開封第一講書人閱讀 156,531評(píng)論 0 345
  • 文/不壞的土叔 我叫張陵虎韵,是天一觀的道長易稠。 經(jīng)常有香客問我,道長包蓝,這世上最難降的妖魔是什么驶社? 我笑而不...
    開封第一講書人閱讀 56,309評(píng)論 1 282
  • 正文 為了忘掉前任,我火速辦了婚禮测萎,結(jié)果婚禮上亡电,老公的妹妹穿的比我還像新娘。我一直安慰自己硅瞧,他們只是感情好份乒,可當(dāng)我...
    茶點(diǎn)故事閱讀 65,381評(píng)論 5 384
  • 文/花漫 我一把揭開白布。 她就那樣靜靜地躺著,像睡著了一般或辖。 火紅的嫁衣襯著肌膚如雪瘾英。 梳的紋絲不亂的頭發(fā)上,一...
    開封第一講書人閱讀 49,730評(píng)論 1 289
  • 那天颂暇,我揣著相機(jī)與錄音缺谴,去河邊找鬼。 笑死耳鸯,一個(gè)胖子當(dāng)著我的面吹牛湿蛔,可吹牛的內(nèi)容都是我干的。 我是一名探鬼主播县爬,決...
    沈念sama閱讀 38,882評(píng)論 3 404
  • 文/蒼蘭香墨 我猛地睜開眼阳啥,長吁一口氣:“原來是場噩夢啊……” “哼!你這毒婦竟也來了捌省?” 一聲冷哼從身側(cè)響起苫纤,我...
    開封第一講書人閱讀 37,643評(píng)論 0 266
  • 序言:老撾萬榮一對(duì)情侶失蹤,失蹤者是張志新(化名)和其女友劉穎纲缓,沒想到半個(gè)月后卷拘,有當(dāng)?shù)厝嗽跇淞掷锇l(fā)現(xiàn)了一具尸體,經(jīng)...
    沈念sama閱讀 44,095評(píng)論 1 303
  • 正文 獨(dú)居荒郊野嶺守林人離奇死亡祝高,尸身上長有42處帶血的膿包…… 初始之章·張勛 以下內(nèi)容為張勛視角 年9月15日...
    茶點(diǎn)故事閱讀 36,448評(píng)論 2 325
  • 正文 我和宋清朗相戀三年栗弟,在試婚紗的時(shí)候發(fā)現(xiàn)自己被綠了。 大學(xué)時(shí)的朋友給我發(fā)了我未婚夫和他白月光在一起吃飯的照片工闺。...
    茶點(diǎn)故事閱讀 38,566評(píng)論 1 339
  • 序言:一個(gè)原本活蹦亂跳的男人離奇死亡乍赫,死狀恐怖,靈堂內(nèi)的尸體忽然破棺而出陆蟆,到底是詐尸還是另有隱情雷厂,我是刑警寧澤,帶...
    沈念sama閱讀 34,253評(píng)論 4 328
  • 正文 年R本政府宣布叠殷,位于F島的核電站改鲫,受9級(jí)特大地震影響,放射性物質(zhì)發(fā)生泄漏林束。R本人自食惡果不足惜像棘,卻給世界環(huán)境...
    茶點(diǎn)故事閱讀 39,829評(píng)論 3 312
  • 文/蒙蒙 一、第九天 我趴在偏房一處隱蔽的房頂上張望壶冒。 院中可真熱鬧缕题,春花似錦、人聲如沸胖腾。這莊子的主人今日做“春日...
    開封第一講書人閱讀 30,715評(píng)論 0 21
  • 文/蒼蘭香墨 我抬頭看了看天上的太陽。三九已至瓶摆,卻和暖如春凉逛,著一層夾襖步出監(jiān)牢的瞬間,已是汗流浹背群井。 一陣腳步聲響...
    開封第一講書人閱讀 31,945評(píng)論 1 264
  • 我被黑心中介騙來泰國打工状飞, 沒想到剛下飛機(jī)就差點(diǎn)兒被人妖公主榨干…… 1. 我叫王不留,地道東北人书斜。 一個(gè)月前我還...
    沈念sama閱讀 46,248評(píng)論 2 360
  • 正文 我出身青樓诬辈,卻偏偏與公主長得像,于是被迫代替她去往敵國和親荐吉。 傳聞我的和親對(duì)象是個(gè)殘疾皇子焙糟,可洞房花燭夜當(dāng)晚...
    茶點(diǎn)故事閱讀 43,440評(píng)論 2 348