本文章來自自強(qiáng)學(xué)堂:http://www.ziqiangxuetang.com/django/django-tutorial.html
在前面的幾節(jié)中我們都是用簡(jiǎn)單的 django.http.HttpResponse 來把內(nèi)容顯示到網(wǎng)頁(yè)上眼虱,本節(jié)將講解如何使用渲染模板的方法來顯示內(nèi)容脖祈。
1端盆,創(chuàng)建一個(gè)zjyd_temp項(xiàng)目皂岔,和一個(gè)名稱為 learn 的應(yīng)用:
django-admin startproject zjyd_temp
cd zjyd_temp
python manage.py startapp learn
2信柿,把 learn 加入到 settings.INSTALLED_APPS中
INSTALLED_APPS = [
'django.contrib.admin',
'django.contrib.auth',
'django.contrib.contenttypes',
'django.contrib.sessions',
'django.contrib.messages',
'django.contrib.staticfiles',
'learn',
]
3, 打開 learn/views.py 寫一個(gè)首頁(yè)的視圖
from django.shortcuts import render
# Create your views here.
def home(request):
return render(request,'home.html')
4闲延, 在 learn目錄下新建一個(gè) templates 文件夾立磁,里面新建一個(gè) home.html
默認(rèn)配置下,Django 的模板系統(tǒng)會(huì)自動(dòng)找到app下面的templates文件夾中的模板文件晃洒。
目錄結(jié)構(gòu)為:
zjyd_temp
├── learn
│ ├── admin.py
│ ├── apps.py
│ ├── __init__.py
│ ├── migrations
│ │ └── __init__.py
│ ├── models.py
│ ├── templates
│ │ └── home.html
│ ├── tests.py
│ └── views.py
├── manage.py
└── zjyd_temp
├── __init__.py
├── __pycache__
│ ├── __init__.cpython-35.pyc
│ └── settings.cpython-35.pyc
├── settings.py
├── urls.py
└── wsgi.py
5慨灭,在home.html中寫一些內(nèi)容
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<title>Django</title>
</head>
<body>
你好,Django
</body>
</html>
6球及,將視圖函數(shù)對(duì)應(yīng)到網(wǎng)址氧骤,更改urls.py
from learn import views as learn_views
urlpatterns = [
url(r'^$',learn_views.home,name='home'),
url(r'^admin/', admin.site.urls),
]
7,創(chuàng)建數(shù)據(jù)庫(kù)表
python manage.py migrate
創(chuàng)建數(shù)據(jù)庫(kù)雖然本節(jié)不會(huì)用到桶略,但是可以讓一些提示消失(提示你要?jiǎng)?chuàng)建數(shù)據(jù)庫(kù)之類的)
運(yùn)行程序语淘,結(jié)果如下:
關(guān)于模板的一些知識(shí):
網(wǎng)站模板的設(shè)計(jì)诲宇,一般的,我們做網(wǎng)站有一些通用的部分惶翻,比如 導(dǎo)航姑蓝,底部,訪問統(tǒng)計(jì)代碼等等
nav.html, bottom.html, count.html
<!DOCTYPE html>
<html>
<head>
<title>{% block title %}默認(rèn)標(biāo)題{% endblock %} - 自強(qiáng)學(xué)堂</title>
</head>
<body>
{% include 'nav.html' %}
{% block content %}
<div>這里是默認(rèn)內(nèi)容吕粗,所有繼承自這個(gè)模板的纺荧,如果不覆蓋就顯示這里的默認(rèn)內(nèi)容。</div>
{% endblock %}
{% include 'bottom.html' %}
{% include 'count.html' %}
</body>
</html>
如果需要颅筋,寫足夠多的 block 以便繼承的模板可以重寫該部分宙暇,include 是包含其它文件的內(nèi)容,就是把一些網(wǎng)頁(yè)共用的部分拿出來议泵,重復(fù)利用占贫,改動(dòng)的時(shí)候也方便一些,還可以把廣告代碼放在一個(gè)單獨(dú)的html中先口,改動(dòng)也方便一些型奥,在用到的地方include進(jìn)去。其它的頁(yè)面繼承自 base.html 就好了碉京,繼承后的模板也可以在 block 塊中 include 其它的模板文件厢汹。
比如我們的首頁(yè) home.html,繼承或者說擴(kuò)展(extends)原來的 base.html谐宙,可以簡(jiǎn)單這樣寫烫葬,重寫部分代碼(默認(rèn)值的那一部分不用改)
{% extends 'base.html' %}
{% block title %}歡迎光臨首頁(yè){% endblock %}
{% block content %}
{% include 'ad.html' %}
這里是首頁(yè),歡迎光臨
{% endblock %}
注意:模板一般放在app下的templates中凡蜻,Django會(huì)自動(dòng)去這個(gè)文件夾中找搭综。但 假如我們每個(gè)app的templates中都有一個(gè) index.html,當(dāng)我們?cè)趘iews.py中使用的時(shí)候咽瓷,直接寫一個(gè) render(request, 'index.html')设凹,Django 能不能找到當(dāng)前 app 的 templates 文件夾中的 index.html 文件夾呢?(答案是不一定能,有可能找錯(cuò))
Django 模板查找機(jī)制: Django 查找模板的過程是在每個(gè) app 的 templates 文件夾中找(而不只是當(dāng)前 app 中的代碼只在當(dāng)前的 app 的 templates 文件夾中找)茅姜。各個(gè) app 的 templates 形成一個(gè)文件夾列表闪朱,Django 遍歷這個(gè)列表,一個(gè)個(gè)文件夾進(jìn)行查找钻洒,當(dāng)在某一個(gè)文件夾找到的時(shí)候就停止奋姿,所有的都遍歷完了還找不到指定的模板的時(shí)候就是 Template Not Found (過程類似于Python找包)。這樣設(shè)計(jì)有利當(dāng)然也有弊素标,有利是的地方是一個(gè)app可以用另一個(gè)app的模板文件称诗,弊是有可能會(huì)找錯(cuò)了。所以我們使用的時(shí)候在 templates 中建立一個(gè) app 同名的文件夾头遭,這樣就好了寓免。
這就需要把每個(gè)app中的 templates 文件夾中再建一個(gè) app 的名稱癣诱,僅和該app相關(guān)的模板放在 app/templates/app/ 目錄下面,
例如:項(xiàng)目 zqxt 有兩個(gè) app袜香,分別為 tutorial 和 tryit
zqxt
├── tutorial
│ ├── __init__.py
│ ├── admin.py
│ ├── models.py
│ ├── templates
│ │ └── tutorial
│ │ ├── index.html
│ │ └── search.html
│ ├── tests.py
│ └── views.py
├── tryit
│ ├── __init__.py
│ ├── admin.py
│ ├── models.py
│ ├── templates
│ │ └── tryit
│ │ ├── index.html
│ │ └── poll.html
│ ├── tests.py
│ └── views.py
├── manage.py
└── zqxt
├── __init__.py
├── settings.py
├── urls.py
└── wsgi.py
這樣撕予,使用的時(shí)候,模板就是 "tutorial/index.html" 和 "tryit/index.html" 這樣有app作為名稱的一部分蜈首,就不會(huì)混淆实抡。
下面我們看Django模板中的循環(huán),條件判斷欢策,常用的標(biāo)簽吆寨,過濾器的使用。
列表踩寇,字典啄清,類的實(shí)例的使用
循環(huán):迭代顯示列表,字典等中的內(nèi)容
條件判斷:判斷是否顯示該內(nèi)容姑荷,比如判斷是手機(jī)訪問盒延,還是電腦訪問,給出不一樣的代碼鼠冕。
標(biāo)簽:for,if 這樣的功能都是標(biāo)簽胯盯。
過濾器:管道符號(hào)后面的功能懈费,比如{{ var|length }},求變量長(zhǎng)度的 length 就是一個(gè)過濾器博脑。
如果需要將一個(gè)或者多個(gè)變量共享給多個(gè)網(wǎng)頁(yè)或所有網(wǎng)頁(yè)使用憎乙,比如在網(wǎng)頁(yè)上顯示來訪者的IP,這個(gè)可以使用 Django 上下文渲染器 來做叉趣。
栗子一:顯示一個(gè)基本的字符串在網(wǎng)頁(yè)上
編輯views.py
from django.shortcuts import render
# Create your views here.
def home(request):
string = u"像啃磚頭一樣啃Django"
return render(request,'home.html',{'string':string})
在視圖中我們傳遞了一個(gè)字符串名稱是 string 到模板 home.html泞边,在模板中這樣使用它:
<body>
{{ string }}
</body>
運(yùn)行結(jié)果為:
栗子二:基本的 for 循環(huán) 和 List內(nèi)容的顯示
修改views.py
from django.shortcuts import render
# Create your views here.
def home(request):
TutorialList = ['Html','CSS','JQuery','Python']
return render(request,'home.html',{'TutorialList':TutorialList})
在視圖中我們傳遞了一個(gè)List到模板 home.html,在模板中這樣使用它:
<body>
教程列表:
{% for i in TutorialList %}
{{ i }}
{% endfor %}
</body>
注意:for 循環(huán)要有一個(gè)結(jié)束標(biāo)記
總結(jié)一下:一般的變量之類用的是 {{ }}(變量)疗杉,功能類的阵谚,比如循環(huán),條件判斷是用{% %}(標(biāo)簽)
栗子三:顯示字典中內(nèi)容:
修改 views.py
from django.shortcuts import render
# Create your views here.
def home(request):
info_dict = {'work':u'運(yùn)維','content':u'苦逼'}
return render(request,'home.html',{'info_dict':info_dict})
修改home.html
<body>
工作:{{ info_dict.work }} 內(nèi)容:{{ info_dict.content }}
</body>
注意:在模板中取字典的鍵是用點(diǎn) info_dict.work 烟具,而不是python中的info_dict['work']梢什,運(yùn)行結(jié)果如下:
還可以按照下面的方法遍歷字典:
{% for key, value in info_dict.items %}
{{ key }}: {{ value }}
{% endfor %}
運(yùn)行結(jié)果為:
栗子四:在模板中進(jìn)行 條件判斷和for循環(huán)的詳細(xì)操作
修改views.py
from django.shortcuts import render
# Create your views here.
def home(request):
List = map(str,range(100))
return render(request,'home.html',{'List':List})
在模板中我們用逗號(hào)將生成的元素連起來:
<body>
{% for item in List %}
{{ item}},
{% endfor %}
</body>
運(yùn)行程序:
我們發(fā)現(xiàn)最后一個(gè)元素后面存在一個(gè) , 號(hào)。我們可以使用forloop.last變量來判斷是否為最后一項(xiàng):
<body>
{% for item in List %}
{{ item}}{% if not forloop.last %},{% endif %}
{% endfor %}
</body>
運(yùn)行程序:
在for循環(huán)中朝聋,一些變量及其描述:
forloop.counter 索引從1開始算
forloop.counter0 索引從0開始算
forloop.revcounter 索引從最大長(zhǎng)度到1
forloop.revcounter0 索引從最大長(zhǎng)度到0
forloop.first 當(dāng)遍歷的元素為第一項(xiàng)時(shí)為真
forloop.last 當(dāng)遍歷的元素為最后一項(xiàng)時(shí)為真
forloop.parentloop 用在嵌套的for循環(huán)中嗡午,獲取上一層for循環(huán)的forloop
當(dāng)列表中可能為空值時(shí)用 for empty
<ul>
{% for athlete in athlete_list %}
<li>{{ athlete.name }}</li>
{% empty %}
<li>抱歉,列表為空</li>
{% endfor %}
</ul>
栗子五:模板上得到視圖對(duì)應(yīng)的網(wǎng)址
# views.py
def add(request, a, b):
c = int(a) + int(b)
return HttpResponse(str(c))
# urls.py
urlpatterns = patterns('',
url(r'^add/(\d+)/(\d+)/$', 'app.views.add', name='add'),
)
# template html
{% url 'add' 4 5 %}
這樣網(wǎng)址上就會(huì)顯示出:/add/4/5/ 這個(gè)網(wǎng)址冀痕,假如我們以后修改 urls.py 中的
r'^add/(\d+)/(\d+)/$'
這一部分荔睹,改成另的狸演,比如:
r'^jiafa/(\d+)/(\d+)/$'
這樣,我們不需要再次修改模板僻他,當(dāng)再次訪問的時(shí)候严沥,網(wǎng)址會(huì)自動(dòng)變成 /jiafa/4/5/
還可以使用as語句將內(nèi)容取別名(相當(dāng)于定義一個(gè)變量),多次使用(但視圖名稱到網(wǎng)址轉(zhuǎn)換只進(jìn)行了一次)
{% url 'some-url-name' arg arg2 as the_url %}
<a href="{{ the_url }}">鏈接到:{{ the_url }}</a>
栗子六:模板中的邏輯操作
==, !=, >=, <=, >, < 這些比較都可以在模板中使用中姜,比如:
{% if var >= 90 %}
成績(jī)優(yōu)秀
{% elif var >= 80 %}
成績(jī)良好
{% elif var >= 70 %}
成績(jī)一般
{% elif var >= 60 %}
需要努力
{% else %}
不及格
{% endif %}
and, or, not, in, not in 也可以在模板中使用
假如我們判斷 num 是不是在 0 到 100 之間:
{% if num <= 100 and num >= 0 %}
num在0到100之間
{% else %}
數(shù)值不在范圍之內(nèi)消玄!
{% endif %}
假如我們判斷 'django 在不在一個(gè)列表變量 List 中:
{% if 'django' in List %}
django在列表中
{% endif %}
栗子七:在模板中獲取當(dāng)前網(wǎng)址,當(dāng)前用戶等:
獲取當(dāng)前用戶:
{{ request.user }}
如果登陸就顯示內(nèi)容丢胚,不登陸就不顯示內(nèi)容:
{% if request.user.is_authenticated %}
{{ request.user.username }}翩瓜,您好!
{% else %}
請(qǐng)登陸携龟,這里放登陸鏈接
{% endif %}
獲取當(dāng)前網(wǎng)址:
{{ request.path }}
獲取當(dāng)前 GET 參數(shù):
{{ request.GET.urlencode }}
合并到一起用的一個(gè)例子:
<a href="{{ request.path }}?{{ request.GET.urlencode }}&delete=1">當(dāng)前網(wǎng)址加參數(shù) delete</a>
我們可以判斷 delete 參數(shù)是不是 1 來刪除當(dāng)前的頁(yè)面內(nèi)容兔跌。