本文章来自自强学堂:http://www.ziqiangxuetang.com/django/django-tutorial.html
在前面的几节中我们都是用简单的 django.http.HttpResponse 来把内容显示到网页上,本节将讲解如何使用渲染模板的方法来显示内容。
1,创建一个zjyd_temp项目,和一个名称为 learn 的应用:
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 写一个首页的视图
from django.shortcuts import render
# Create your views here.
def home(request):
return render(request,'home.html')
4, 在 learn目录下新建一个 templates 文件夹,里面新建一个 home.html
默认配置下,Django 的模板系统会自动找到app下面的templates文件夹中的模板文件。
目录结构为:
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中写一些内容
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<title>Django</title>
</head>
<body>
你好,Django
</body>
</html>
6,将视图函数对应到网址,更改urls.py
from learn import views as learn_views
urlpatterns = [
url(r'^$',learn_views.home,name='home'),
url(r'^admin/', admin.site.urls),
]
7,创建数据库表
python manage.py migrate
创建数据库虽然本节不会用到,但是可以让一些提示消失(提示你要创建数据库之类的)
运行程序,结果如下:
关于模板的一些知识:
网站模板的设计,一般的,我们做网站有一些通用的部分,比如 导航,底部,访问统计代码等等
nav.html, bottom.html, count.html
<!DOCTYPE html>
<html>
<head>
<title>{% block title %}默认标题{% endblock %} - 自强学堂</title>
</head>
<body>
{% include 'nav.html' %}
{% block content %}
<div>这里是默认内容,所有继承自这个模板的,如果不覆盖就显示这里的默认内容。</div>
{% endblock %}
{% include 'bottom.html' %}
{% include 'count.html' %}
</body>
</html>
如果需要,写足够多的 block 以便继承的模板可以重写该部分,include 是包含其它文件的内容,就是把一些网页共用的部分拿出来,重复利用,改动的时候也方便一些,还可以把广告代码放在一个单独的html中,改动也方便一些,在用到的地方include进去。其它的页面继承自 base.html 就好了,继承后的模板也可以在 block 块中 include 其它的模板文件。
比如我们的首页 home.html,继承或者说扩展(extends)原来的 base.html,可以简单这样写,重写部分代码(默认值的那一部分不用改)
{% extends 'base.html' %}
{% block title %}欢迎光临首页{% endblock %}
{% block content %}
{% include 'ad.html' %}
这里是首页,欢迎光临
{% endblock %}
注意:模板一般放在app下的templates中,Django会自动去这个文件夹中找。但 假如我们每个app的templates中都有一个 index.html,当我们在views.py中使用的时候,直接写一个 render(request, 'index.html'),Django 能不能找到当前 app 的 templates 文件夹中的 index.html 文件夹呢?(答案是不一定能,有可能找错)
Django 模板查找机制: Django 查找模板的过程是在每个 app 的 templates 文件夹中找(而不只是当前 app 中的代码只在当前的 app 的 templates 文件夹中找)。各个 app 的 templates 形成一个文件夹列表,Django 遍历这个列表,一个个文件夹进行查找,当在某一个文件夹找到的时候就停止,所有的都遍历完了还找不到指定的模板的时候就是 Template Not Found (过程类似于Python找包)。这样设计有利当然也有弊,有利是的地方是一个app可以用另一个app的模板文件,弊是有可能会找错了。所以我们使用的时候在 templates 中建立一个 app 同名的文件夹,这样就好了。
这就需要把每个app中的 templates 文件夹中再建一个 app 的名称,仅和该app相关的模板放在 app/templates/app/ 目录下面,
例如:项目 zqxt 有两个 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
这样,使用的时候,模板就是 "tutorial/index.html" 和 "tryit/index.html" 这样有app作为名称的一部分,就不会混淆。
下面我们看Django模板中的循环,条件判断,常用的标签,过滤器的使用。
列表,字典,类的实例的使用
循环:迭代显示列表,字典等中的内容
条件判断:判断是否显示该内容,比如判断是手机访问,还是电脑访问,给出不一样的代码。
标签:for,if 这样的功能都是标签。
过滤器:管道符号后面的功能,比如{{ var|length }},求变量长度的 length 就是一个过滤器。
如果需要将一个或者多个变量共享给多个网页或所有网页使用,比如在网页上显示来访者的IP,这个可以使用 Django 上下文渲染器 来做。
栗子一:显示一个基本的字符串在网页上
编辑views.py
from django.shortcuts import render
# Create your views here.
def home(request):
string = u"像啃砖头一样啃Django"
return render(request,'home.html',{'string':string})
在视图中我们传递了一个字符串名称是 string 到模板 home.html,在模板中这样使用它:
<body>
{{ string }}
</body>
运行结果为:
栗子二:基本的 for 循环 和 List内容的显示
修改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})
在视图中我们传递了一个List到模板 home.html,在模板中这样使用它:
<body>
教程列表:
{% for i in TutorialList %}
{{ i }}
{% endfor %}
</body>
注意:for 循环要有一个结束标记
总结一下:一般的变量之类用的是 {{ }}(变量),功能类的,比如循环,条件判断是用{% %}(标签)
栗子三:显示字典中内容:
修改 views.py
from django.shortcuts import render
# Create your views here.
def home(request):
info_dict = {'work':u'运维','content':u'苦逼'}
return render(request,'home.html',{'info_dict':info_dict})
修改home.html
<body>
工作:{{ info_dict.work }} 内容:{{ info_dict.content }}
</body>
注意:在模板中取字典的键是用点 info_dict.work ,而不是python中的info_dict['work'],运行结果如下:
还可以按照下面的方法遍历字典:
{% for key, value in info_dict.items %}
{{ key }}: {{ value }}
{% endfor %}
运行结果为:
栗子四:在模板中进行 条件判断和for循环的详细操作
修改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})
在模板中我们用逗号将生成的元素连起来:
<body>
{% for item in List %}
{{ item}},
{% endfor %}
</body>
运行程序:
我们发现最后一个元素后面存在一个 , 号。我们可以使用forloop.last变量来判断是否为最后一项:
<body>
{% for item in List %}
{{ item}}{% if not forloop.last %},{% endif %}
{% endfor %}
</body>
运行程序:
在for循环中,一些变量及其描述:
forloop.counter 索引从1开始算
forloop.counter0 索引从0开始算
forloop.revcounter 索引从最大长度到1
forloop.revcounter0 索引从最大长度到0
forloop.first 当遍历的元素为第一项时为真
forloop.last 当遍历的元素为最后一项时为真
forloop.parentloop 用在嵌套的for循环中,获取上一层for循环的forloop
当列表中可能为空值时用 for empty
<ul>
{% for athlete in athlete_list %}
<li>{{ athlete.name }}</li>
{% empty %}
<li>抱歉,列表为空</li>
{% endfor %}
</ul>
栗子五:模板上得到视图对应的网址
# 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 %}
这样网址上就会显示出:/add/4/5/ 这个网址,假如我们以后修改 urls.py 中的
r'^add/(\d+)/(\d+)/$'
这一部分,改成另的,比如:
r'^jiafa/(\d+)/(\d+)/$'
这样,我们不需要再次修改模板,当再次访问的时候,网址会自动变成 /jiafa/4/5/
还可以使用as语句将内容取别名(相当于定义一个变量),多次使用(但视图名称到网址转换只进行了一次)
{% url 'some-url-name' arg arg2 as the_url %}
<a href="{{ the_url }}">链接到:{{ the_url }}</a>
栗子六:模板中的逻辑操作
==, !=, >=, <=, >, < 这些比较都可以在模板中使用,比如:
{% if var >= 90 %}
成绩优秀
{% elif var >= 80 %}
成绩良好
{% elif var >= 70 %}
成绩一般
{% elif var >= 60 %}
需要努力
{% else %}
不及格
{% endif %}
and, or, not, in, not in 也可以在模板中使用
假如我们判断 num 是不是在 0 到 100 之间:
{% if num <= 100 and num >= 0 %}
num在0到100之间
{% else %}
数值不在范围之内!
{% endif %}
假如我们判断 'django 在不在一个列表变量 List 中:
{% if 'django' in List %}
django在列表中
{% endif %}
栗子七:在模板中获取当前网址,当前用户等:
获取当前用户:
{{ request.user }}
如果登陆就显示内容,不登陆就不显示内容:
{% if request.user.is_authenticated %}
{{ request.user.username }},您好!
{% else %}
请登陆,这里放登陆链接
{% endif %}
获取当前网址:
{{ request.path }}
获取当前 GET 参数:
{{ request.GET.urlencode }}
合并到一起用的一个例子:
<a href="{{ request.path }}?{{ request.GET.urlencode }}&delete=1">当前网址加参数 delete</a>
我们可以判断 delete 参数是不是 1 来删除当前的页面内容。