https://code.ziqiangxuetang.com/django/django-context-processors.html
有時候我們想讓一些內容在多個模板中都要有,比如導航內容,我們又不想每個視圖函數都寫一次這些變量內容,怎么辦呢?
這時候就可以用 Django 上下文渲染器來解決。
一,初識上下文渲染器
我們從視圖函數說起,在 views.py 中返回字典在模板中使用:
1
2
3
4
|
from
django.shortcuts
import
render
def
home(request):
return
render(request,
'home.html'
, {
'info'
:
'Welcome to ziqiangxuetang.com !'
})
|
這樣我們就可以在模板中使用 info 這個變量了。
request 函數就是在返回一個字典,每一個模板中都可以使用這個字典中提供的 request 變量.
1
|
{{ info }}
|
模板對應的地方就會顯示:Welcome to ziqiangxuetang.com !
但是如果我們有一個變量,比如用戶的IP,想顯示在網站的每個網頁上。再比如顯示一些導航信息在每個網頁上,該怎么做呢?
一種方法是用死代碼,直接把欄目固定寫在 模塊中,這個對於不經常變動的來說也是一個辦法,簡單高效。
但是像用戶IP這樣的因人而異的,或者經常變動的,就不得不想一個更好的解決辦法了。
由於上下文渲染器API在Django 1.8 時發生了變化,被移動到了 tempate 文件夾下,所以講解的時候分兩種,一種是 Django 1.8 及以后的,和Django 1.7及以前的。
我們來看Django官方自帶的小例子:
Django 1.8 版本:
django.template.context_processors 中有這樣一個函數
1
2
|
def
request(request):
return
{
'request'
: request}
|
其中的每一個函數都對應一個渲染器
Django 1.7 及以前的代碼在這里:django.core.context_processors.request 函數是一樣的。
在settings.py 中:
Django 1.8 版本 settings.py:
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
|
TEMPLATES
=
[
{
'BACKEND'
:
'django.template.backends.django.DjangoTemplates'
,
'DIRS'
: [],
'APP_DIRS'
:
True
,
'OPTIONS'
: {
'context_processors'
: [
'django.template.context_processors.debug'
,
'django.template.context_processors.request'
,
'django.contrib.auth.context_processors.auth'
,
'django.contrib.messages.context_processors.messages'
,
],
},
},
]
|
Django 1.7 版本 settings.py 默認是這樣的:
1
2
3
4
5
6
7
8
9
|
TEMPLATE_CONTEXT_PROCESSORS
=
(
"django.contrib.auth.context_processors.auth"
,
"django.core.context_processors.debug"
,
"django.core.context_processors.i18n"
,
"django.core.context_processors.media"
,
"django.core.context_processors.static"
,
"django.core.context_processors.tz"
,
"django.contrib.messages.context_processors.messages"
)
|
我們可以手動添加 request 的渲染器
1
2
3
4
5
|
TEMPLATE_CONTEXT_PROCESSORS
=
(
...
"django.core.context_processors.request"
,
...
)
|
這里的 context_processors 中放了一系列的 渲染器,上下文渲染器/context_processor 其實就是函數返回字典(返回字典的函數),字典的 keys 可以用在模板(*.html中的django變量,例如{{ django_var }})中。
request 函數就是在返回一個字典,每一個模板中都可以使用這個字典中提供的 request 變量。
比如在template 中 獲取當前訪問的用戶的用戶名:
1
|
User Name: {{ request.user.username }}
|
二,動手寫個上下文渲染器
2.1 新建一個項目,基於 Django 1.8,低版本的請自行修改對應地方:
1
2
3
|
django-admin.py startproject zqxt
cd
zqxt
python manage.py startapp blog
|
我們新建了 zqxt 項目和 blog 這個應用。
把 blog 這個app 加入到 settings.py 中
1
2
3
4
5
6
|
INSTALLED_APPS
=
(
'django.contrib.admin'
,
...
'blog'
,
)
|
整個項目當前目錄結構如下:
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
|
zqxt
├── blog
│ ├── __init__.py
│ ├── admin.py
│ ├── migrations
│ │ └── __init__.py
│ ├── models.py
│ ├── tests.py
│ └── views.py
├── manage.py
└── zqxt
├── __init__.py
├── settings.py
├── urls.py
└── wsgi.py
|
2.2 我們在 zqxt/zqxt/ 這個目錄下(與settings.py 在一起)新建一個 context_processor.py
1
2
3
4
5
6
7
8
9
10
11
12
13
14
|
#!/usr/bin/env python
# -*- coding: utf-8 -*-
# @Date : 2015-10-31 14:26:26
# @Author : Weizhong Tu (mail@tuweizhong.com)
from django.conf import settings as original_settings
def
settings(request):
return
{
'settings'
: original_settings}
def
ip_address(request):
return
{
'ip_address'
: request.META[
'REMOTE_ADDR'
]}
|
2.3 我們把新建的兩個上下文渲染器(一個函數就是一個context_processor)加入到 settings.py 中:
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
|
TEMPLATES
=
[
{
'BACKEND'
:
'django.template.backends.django.DjangoTemplates'
,
'DIRS'
: [],
'APP_DIRS'
:
True
,
'OPTIONS'
: {
'context_processors'
: [
'django.template.context_processors.debug'
,
'django.template.context_processors.request'
,
'django.contrib.auth.context_processors.auth'
,
'django.contrib.messages.context_processors.messages'
,
'zqxt.context_processor.settings' ,
'zqxt.context_processor.ip_address' ,
],
},
},
]
|
最后面兩個是我們新加入的,我們稍后在模板中測試它。
2.4 修改 blog/views.py 【view視圖,數據處理】
1
2
3
4
5
6
7
8
9
|
from
django.shortcuts
import
render
def
index(reuqest):
return
render(reuqest,
'blog/index.html'
)
def
columns(request):
return
render(request,
'blog/columns.html'
)
|
2.5 新建兩個模板文件,放在 zqxt/blog/templates/blog/ 中
index.html 【*.html模版,數據展示】
request 函數就是在返回一個字典,每一個模板中都可以使用這個字典中提供的 request 變量。
1
2
3
4
5
|
<
h1
>Blog Home Page</
h1
>
DEBUG: {{ settings.DEBUG }}
ip: {{ ip_address }}
|
columns.html
request 函數就是在返回一個字典,每一個模板中都可以使用這個字典中提供的 request 變量。
1
2
3
4
5
|
<
h1
>Blog Columns</
h1
>
DEBUG: {{ settings.DEBUG }}
ip: {{ ip_address }}
|
2.6 修改 zqxt/urls.py
1
2
3
4
5
6
7
8
9
|
from
django.conf.urls
import
include, url
from
django.contrib
import
admin
from
blog
import
views as blog_views
urlpatterns
=
[
url(r
'^blog_home/$'
, blog_views.index),
url(r
'^blog_columns/$'
, blog_views.columns),
url(r
'^admin/'
, include(admin.site.urls)),
]
|
2.7 打開開發服務器並訪問,進行測試吧:
1
|
python manage.py runserver
|
就會看到所有的模板都可以使用 settings 和 ip_address 變量:
http://127.0.0.1:8000/blog_home/
http://127.0.0.1:8000/blog_columns/
效果圖:
最后,附上源代碼下載:zqxt_context_processor.zip