Re: [問題] Django {% csrf_token %}

作者: djshen (djshen)   2017-08-04 22:25:01
先來看看csrf_token做了什麼事
django.template.defaulttags.csrf_token
#1 http://imgur.com/zF9wpKH
django.template.defaulttags.CsrfTokenNode.render
#2 http://imgur.com/wFTXzR1
注意這邊的context.get('csrf_token')
也就是說context裡面要有'csrf_token'
csrf_token template tag才會有東西
那context裡面的csrf_token從何而來?
如果你有稍微看過settings.py的話
應該會在TEMPLATES裡面發現context_processors
這些context processor會自動加東西在context
所以csrf_token應該也是利用context processor加進去的
然後你認真翻了一下source code發現
在django.template.context_processors有個csrf
#3 http://imgur.com/o64Vp1n
這邊他確實產生了csrf_token
但是settings.py裡面卻沒有這個context processor
於是你更認真翻source code
發現django.template.context定義了
_builtin_context_processors = ('django.template.context_processors.csrf',)
#4 http://imgur.com/lQhUVv3
而這個東西被用在django.template.engine.Engine.template_context_processors
#5 http://imgur.com/LbcOIq1
到這邊我們了解csrf context processor是自動加進去的
而上面這些和你的問題有什麼關係?
※ 引述《left (881 forever)》之銘言:
: template = get_template('posting.html')
django.template.loader.get_template
#6 http://imgur.com/mixZLEu
他會return django.template.backends.django.DjangoTemplates.get_template()
也就是django.template.backends.django.Template
#7 http://imgur.com/KOFVrUx
這邊跳了幾步 不過不影響
: request_context = RequestContext(request)
: request_context.push(locals())
: html = template.render(request_context)
這邊call上圖的Template.render
然後是django.template.context.make_context
#8 http://imgur.com/jql8ohU
注意傳進去的參數 request=None
使得回傳的是django.template.context.Context
而不是RequestContext
差別在於#7執行到self.template.render(context)
跳到django.template.base.Template.render
#9 http://imgur.com/tqg1vbf
context.bind_template(self)
比較一下Context和RequestContext的bind_template
Context:
#10 http://imgur.com/M8T1kn4
RequestContext:
#11 http://imgur.com/KysHULW
有沒有看到一個熟悉的東西 template.engine.template_context_processors
剛才我們知道這裡面有csrf context processor
所以當傳入django.template.base.Template.render的context是Context的時候
就不會有csrf_token
: return HttpResponse(html)
: 也就是改成
: return render(request, ‘posting.html’,locals())
那我們來看這邊做了什麼
django.shortcuts.render
call django.template.loader.render_to_string
#12 http://imgur.com/rgUnbMu
django.template.loader.get_template
拿到django.template.backends.django.Template
和上面一樣
但這邊有把request傳給render
造成make_context有拿到request所以回傳RequestContext
剩下的上面都講過了
: 結果錯誤訊息就不見了
: 我想要問各位大大,書上的寫法有錯嗎?
: 如果有,要怎麼用RequestContext以及template.render()改到對?
: 如果沒有,我是死在哪邊? xd
作者: Sunal (SSSSSSSSSSSSSSSSSSSSSSS)   2017-08-04 22:42:00
推推
作者: uranusjr (←這人是超級笨蛋)   2017-08-04 22:47:00
欸其實上面那個也有傳 request, 也有呼叫 make_context真正的重點在上下兩個 template.render 是不一樣的
作者: djshen (djshen)   2017-08-04 22:48:00
make_context的request是從Template.render裡面傳過來
作者: uranusjr (←這人是超級笨蛋)   2017-08-04 22:49:00
所以這樣解釋原 po 應該會覺得怪, 但我也不知道該怎麼講然後原本程式其實改 template.template.render(context)就會過了我覺得要 trace 的話應該要解釋一下 XDDD
作者: djshen (djshen)   2017-08-04 22:50:00
html = template.render(request_context)這邊沒傳request我覺得新手應該不需要了解那麼深啦..沒傳request造成傳給make_context的request也是None
作者: uranusjr (←這人是超級笨蛋)   2017-08-04 22:54:00
是這樣沒錯啦, 不過原書亂挖坑我覺得講一半就不太好, 要嘛就不要講要嘛就整個脈絡要搞清楚; 這整件事最讓我無法理解的是這書竟然在第八頁講這個主題, 到底在搞什麼鬼
作者: Sunal (SSSSSSSSSSSSSSSSSSSSSSS)   2017-08-04 22:59:00
其實django的tutorial對新手就很夠用了
作者: djshen (djshen)   2017-08-04 23:06:00
看起來是1.10改的 https://goo.gl/MtJ3Z2之前會檢查type
作者: Yshuan (倚絃)   2017-08-06 01:58:00
推 這篇超實用
作者: karta0910489 (coyote)   2017-08-06 02:45:00

Links booklink

Contact Us: admin [ a t ] ucptt.com