看我多久能学会Django(三):Django 模板

本文章来自自强学堂: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

创建数据库虽然本节不会用到,但是可以让一些提示消失(提示你要创建数据库之类的)

运行程序,结果如下:

Paste_Image.png

关于模板的一些知识:
网站模板的设计,一般的,我们做网站有一些通用的部分,比如 导航,底部,访问统计代码等等
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>

运行结果为:

Paste_Image.png

栗子二:基本的 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'],运行结果如下:

Paste_Image.png

还可以按照下面的方法遍历字典:

{% for key, value in info_dict.items %}
    {{ key }}: {{ value }}
{% endfor %}

运行结果为:

Paste_Image.png

栗子四:在模板中进行 条件判断和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>

运行程序:


Paste_Image.png

我们发现最后一个元素后面存在一个 , 号。我们可以使用forloop.last变量来判断是否为最后一项:

<body>
{% for item in List %}
{{ item}}{% if not forloop.last %},{% endif %}
{% endfor %}
</body>

运行程序:


Paste_Image.png

在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 来删除当前的页面内容。

最后编辑于
©著作权归作者所有,转载或内容合作请联系作者
  • 序言:七十年代末,一起剥皮案震惊了整个滨河市,随后出现的几起案子,更是在滨河造成了极大的恐慌,老刑警刘岩,带你破解...
    沈念sama阅读 206,723评论 6 481
  • 序言:滨河连续发生了三起死亡事件,死亡现场离奇诡异,居然都是意外死亡,警方通过查阅死者的电脑和手机,发现死者居然都...
    沈念sama阅读 88,485评论 2 382
  • 文/潘晓璐 我一进店门,熙熙楼的掌柜王于贵愁眉苦脸地迎上来,“玉大人,你说我怎么就摊上这事。” “怎么了?”我有些...
    开封第一讲书人阅读 152,998评论 0 344
  • 文/不坏的土叔 我叫张陵,是天一观的道长。 经常有香客问我,道长,这世上最难降的妖魔是什么? 我笑而不...
    开封第一讲书人阅读 55,323评论 1 279
  • 正文 为了忘掉前任,我火速办了婚礼,结果婚礼上,老公的妹妹穿的比我还像新娘。我一直安慰自己,他们只是感情好,可当我...
    茶点故事阅读 64,355评论 5 374
  • 文/花漫 我一把揭开白布。 她就那样静静地躺着,像睡着了一般。 火红的嫁衣衬着肌肤如雪。 梳的纹丝不乱的头发上,一...
    开封第一讲书人阅读 49,079评论 1 285
  • 那天,我揣着相机与录音,去河边找鬼。 笑死,一个胖子当着我的面吹牛,可吹牛的内容都是我干的。 我是一名探鬼主播,决...
    沈念sama阅读 38,389评论 3 400
  • 文/苍兰香墨 我猛地睁开眼,长吁一口气:“原来是场噩梦啊……” “哼!你这毒妇竟也来了?” 一声冷哼从身侧响起,我...
    开封第一讲书人阅读 37,019评论 0 259
  • 序言:老挝万荣一对情侣失踪,失踪者是张志新(化名)和其女友刘颖,没想到半个月后,有当地人在树林里发现了一具尸体,经...
    沈念sama阅读 43,519评论 1 300
  • 正文 独居荒郊野岭守林人离奇死亡,尸身上长有42处带血的脓包…… 初始之章·张勋 以下内容为张勋视角 年9月15日...
    茶点故事阅读 35,971评论 2 325
  • 正文 我和宋清朗相恋三年,在试婚纱的时候发现自己被绿了。 大学时的朋友给我发了我未婚夫和他白月光在一起吃饭的照片。...
    茶点故事阅读 38,100评论 1 333
  • 序言:一个原本活蹦乱跳的男人离奇死亡,死状恐怖,灵堂内的尸体忽然破棺而出,到底是诈尸还是另有隐情,我是刑警宁泽,带...
    沈念sama阅读 33,738评论 4 324
  • 正文 年R本政府宣布,位于F岛的核电站,受9级特大地震影响,放射性物质发生泄漏。R本人自食恶果不足惜,却给世界环境...
    茶点故事阅读 39,293评论 3 307
  • 文/蒙蒙 一、第九天 我趴在偏房一处隐蔽的房顶上张望。 院中可真热闹,春花似锦、人声如沸。这庄子的主人今日做“春日...
    开封第一讲书人阅读 30,289评论 0 19
  • 文/苍兰香墨 我抬头看了看天上的太阳。三九已至,却和暖如春,着一层夹袄步出监牢的瞬间,已是汗流浃背。 一阵脚步声响...
    开封第一讲书人阅读 31,517评论 1 262
  • 我被黑心中介骗来泰国打工, 没想到刚下飞机就差点儿被人妖公主榨干…… 1. 我叫王不留,地道东北人。 一个月前我还...
    沈念sama阅读 45,547评论 2 354
  • 正文 我出身青楼,却偏偏与公主长得像,于是被迫代替她去往敌国和亲。 传闻我的和亲对象是个残疾皇子,可洞房花烛夜当晚...
    茶点故事阅读 42,834评论 2 345

推荐阅读更多精彩内容