# 模版语法
# 模板组件和母版继承
- Django模版引擎中最强大也是最复杂的部分就是模版继承了。模版继承可以让您创建一个基本的“骨架”模版,它包含您站点中的全部元素,并且可以定义能够被子模版覆盖的 blocks 。
# 模块组件:include
include:用于导入html模块(相当于引用一个组件,可在此基础上添加内容)
可以将常用的页面内容如导航条,页尾信息等组件保存在单独的文件中,然后在需要使用的地方,文件的任意位置按如下语法导入即可。 语法:{% include 'navbar.html' %}
下面我们将使用模板继承来进行一个网页的设置
- 第一步:新建一个advertise.html文件
<!DOCTYPE html> <html lang="en"> <head> <meta charset="UTF-8"> <title>Title</title> <link rel="stylesheet" href="https://cdn.bootcss.com/bootstrap/3.3.7/css/bootstrap.min.css"> </head> <body> <div class="row"> <div class="col-md-4"> <div class="advertise"> <div class="panel panel-danger"> <div class="panel-heading">菜单一</div> <div class="panel-body"> Panel content </div> </div> <div class="panel panel-success"> <div class="panel-heading">菜单一</div> <div class="panel-body"> Panel content </div> </div> </div> </div> </div> </body> </html>
修改url.py既views.py文件
url.py文件 urlpatterns = [ path('advertise/', views.advertise), ] views.py文件 def index(request): return render(request,'advertise.html')
第二步:为了使用相同的页面,我们新建一个advertise2.html,你要是开心,你可以完全在这个文件里只写一句话,也能完成advertise.html一样的效果
{% include 'advertise.html' %}
但是实际上你肯定是想做一些改动的,那么我们就可以自己定义新的部分,也就是说advertise.html被当作组件被引用。(即使之前的组件中也有html、head等标签,但是我这里引用时照样可以使用)
```html
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<title>Title</title>
</head>
<body>
<h1>这是第二个页面</h1>
{% include 'advertise.html' %}
</body>
</html>
我们可以查看引入的部分的代码,它被封装成div了(所以include相当于模块的引用)
组件和插件的简单区别
1、组件是提供某一完整功能的模块,如:编辑器组件,QQ空间提供的关注组件 等。而插件更倾向封闭某一功能方法的函数。 2、这两者的区别在 Javascript 里区别很小,组件这个名词用得不多,一般统称插件。
# 模块继承:extends
**extends:**存在有时候一个网址有些地方不会更变,不可能所有的页面都要一个网址,这就需要一个根网页
访问博客园的个人博客,发现很多页面,有几处相同的部分。比如右侧的侧边栏,顶部的导航栏,尾部部分...等等。比如头部,没跳转一个地址,头部都是不变的,不可能每次都重写,所以需要继承。 那么公共区域,不需要自己重复写,继承下来就可以了! #需要注意的是:凡是使用继承的模板的js,导入和使用只能在父级模块中(即base.hmtl)
第一步:修改index.html文件
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<title>Title</title>
<link rel="stylesheet" href="https://cdn.bootcss.com/bootstrap/3.3.7/css/bootstrap.min.css">
<style>
* {
margin: 0;
padding: 0;
}
.header {
width: 100%;
height: 60px;
background-color: #369;
}
.title {
line-height: 60px;
color: white;
font-weight: 100;
margin-left: 20px;
font-size: 20px;
}
.container{
margin-top: 20px;
}
</style>
</head>
<body>
<div class="header">
<p class="title">
路飞学诚
</p>
</div>
<div class="container">
<div class="row">
<div class="col-md-3">
<div class="panel panel-danger">
<div class="panel-heading">菜单一</div>
<div class="panel-body">
Panel content
</div>
</div>
<div class="panel panel-success">
<div class="panel-heading">菜单二</div>
<div class="panel-body">
Panel content
</div>
</div>
<div class="panel panel-warning">
<div class="panel-heading">菜单三</div>
<div class="panel-body">
Panel content
</div>
</div>
</div>
<div class="col-md-9">
<div class="jumbotron">
<h1>Hello, INDEX!</h1>
<p>...</p>
<p><a class="btn btn-primary btn-lg" href="#" role="button">Learn more</a></p>
</div>
</div>
</div>
</div>
</body>
</html>
修改url.py文件。添加视图函数和对应地址
def index(request):
return render(request,'index.html')
def articles(request):
return render(request,'articles.html')
def author(request):
return render(request,'author.html')
#url.py文件
urlpatterns =[
url(r'^app/',views.index),
url(r'^app/articles',views.articles),
url(r'^app/author',views.author),
]
问题来了,为 了使用上面的模板信息,我们必须在新建的两个html文件中,复制粘贴相同的内容,然后添上我们不同的内容?显得特别麻烦。下面我们将使用extend继承模块来解决这个问题:
针对上面模块,我们只需要将我们每次需要改动的部分框起来就行了
#父模块,命名为base.html
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
{% block title %}
<title>title</title>
{% endblock title %}
<link rel="stylesheet" href="https://cdn.bootcss.com/bootstrap/3.3.7/css/bootstrap.min.css"
integrity="sha384-BVYiiSIFeK1dGmJRAkycuHAHRg32OmUcww7on3RYdg4Va+PmSTsz/K68vbdEjh4u" crossorigin="anonymous">
<style>
* {
margin: 0;
padding: 0;
}
.header {
width: 100%;
height: 60px;
background-color: #369;
}
.title {
line-height: 60px;
color: white;
font-weight: 100;
margin-left: 20px;
font-size: 20px;
}
.container{
margin-top: 20px;
}
</style>
</head>
<body>
<div class="header">
<p class="title">
路飞学诚
</p>
</div>
<div class="container">
<div class="row">
<div class="col-md-3">
<div class="panel panel-danger">
<div class="panel-heading"><a href="http://127.0.0.1:8008/index/">首页</a></div>
<div class="panel-body">
Panel content
</div>
</div>
<div class="panel panel-success">
<div class="panel-heading"><a href="http://127.0.0.1:8008/authors/">作者</a></div>
<div class="panel-body">
Panel content
</div>
</div>
<div class="panel panel-warning">
<div class="panel-heading"><a href="http://127.0.0.1:8008/articles/">文章管理</a></div>
<div class="panel-body">
Panel content
</div>
</div>
</div>
<div class="col-md-9">
{% block content %} //变动部分,用来占位置
{% endblock %}
</div>
</div>
</div>
{% block cont %}
{% endblock %}
</body>
</html>
第三步:修改index.html,删除多余的代码。继承base.html它是先继承,再填充内容。
extends 标签是这里的关键。它告诉模版引擎,这个模版“继承”了另一个模版。当模版系统处理这个模版时,首先,它将定位父模版——在此例中,就是“base.html”。
那时,模版引擎将注意到 base.html 中的三个 block 标签,并用子模版中的内容来替换这些block。根据 blog_entries 的值,输出可能看起来是这样的:
#以index.html继承为例
{% extends 'base.html' %}
{% block content %}
<div class="jumbotron">
<h1>Hello, INDEX!</h1>
<p>...</p>
<p><a class="btn btn-primary btn-lg" href="#" role="button">Learn more</a></p>
</div>
{% endblock %}
{% block cont %}
<h1>Here is home 即使base.html中有block,这里也可以不写,但是不能重名</h1>
{% endblock %}
接下来修改articles.html
{% extends 'base.html' %}
{% block content %}
<div class="article_list">
<ul>
<li>红楼梦</li>
<li>三国演义</li>
<li>西游记</li>
<li>水浒传</li>
</ul>
</div>
{% endblock %}
修改author.html
{% extends 'base.html' %}
{% block content %}
<div class="author_list">
<ul>
<li>曹雪芹</li>
<li>罗贯中</li>
<li>吴承恩</li>
<li>施耐庵</li>
</ul>
</div>
{% endblock %}
这样,就解决了代码重复问题
问题二:每次的标题都是title,默认的,我们能不能修改它哪?每次跳出后页面的标题也会跟着变动
同样的使用block块处理:
#以articels.html文件为例 {% extends 'base.html' %} {% block content %} \{\{ block.super }/} <div class="article_list"> <ul> <li>红楼梦</li> <li>三国演义</li> <li>西游记</li> <li>水浒传</li> </ul> </div> {% endblock %} {% block title %} <title>Article</title> {% endblock %}
问题三:文章右侧的内容写死了,我想根据views.py函数的调用,返回不同的值怎么办?
#以articels.html为例 {% extends 'base.html' %} {% block content %} <div class="article_list"> <ul> {% for article in acticle_list %} <li>\{\{ article }/}</li> {% endfor %} </ul> </div> {% endblock %} {% block title %} <title>Article</title> {% endblock %} -------------------------------------------------------------- #author.html文件 {% extends 'base.html' %} {% block content %} <div class="article_list"> <ul> {% for article in acticle_list %} <li>\{\{ article }/}</li> {% endfor %} </ul> </div> {% endblock %} {% block title %} <title>Article</title> {% endblock %}
对应的views.py函数,需要给他传入数据:
def articles(request): acticle_list = ['红楼梦','三国演义','西游记','水浒传'] return render(request, 'articles.html',{'acticle_list':acticle_list}) def authors(request): author_list = ['曹雪芹','罗贯中','吴承恩','施耐庵'] return render(request, 'authors.html',{'author_list':author_list})
通过上面的方法就可以实现基本的页面模块继承了
block.super
如果您需要从父模板获取块的内容,则\{\{block.super}/}变量将执行该操作。如果你想添加父块的内容而不是完全覆盖父块的内容,这很有用。使用\{\{block.super}/}插入的数据不会自动转义(请参阅下一节),因为它已经在父模板中被转义(如有必要);也就是说要使用保留父类的内容使用block.super,不写父类的“无”会被覆盖(上例)
举例:修改base.html,加入h3标签。修改block content部分
{% block content %} <h3>详细内容</h3> {% endblock %}
修改articles.html,在block content 下面一行,增加{{block.super}/},也就是会保留继承的父级模态默认带的样式。
{% extends 'base.html' %} {% block content %} \{\{ block.super }/} <div class="article_list"> <ul> {% for article in acticle_list %} <li>\{\{ article }/}</li> {% endfor %} </ul> </div> {% endblock %} {% block title %} <title>Article</title> {% endblock %}®
继承部分无处不在:我们可以写在一些标签中
<li class="{% block pub_acitve1 %} active {% endblock %}"> …… </li> //默认值为active <li class="{% block pub_acitve2 %} {% endblock %}"> …… </li> ---------------------------------继承方-------------------------- {% block pub_acitve1 %} {% endblock %} {% block pub_acitve2 %} active {% endblock %}
-注意:
1、 {% extends '' %} 语句必须写在子模块的第一行,不然下面都不知道干撒,
2、 子模块是继承父模块,也就是说base.hmtl;可以设置默认值,如果子模块的block没有设置则使用base.html中的:如在base.html中的
{% block title %}<title>无</title>{% endblock %},后面没有就会使用默认的 “无”
3、 在base模版中设置越多的 {% block %} 标签越好。请记住,子模版不必定义全部父模版中的blocks,所以你可以在大多数blocks中填充合的默认内容,然后,只定义你需要的那一个。多一点钩子总比少一点好。
4、 如果你发现你自己在大量的模版中复制内容,那可能意味着你应该把内容移动到父模版中的一个 {% block %} 中。
注意:
1、{% extends base.html %} //这里base.html没有引号,是相当于变量的,是有问题的,但是我们可以在views中传入这个变量{'base.html':'base.html'}
2、我们甚至可以设置js、css内容:{% block js %} {% endblock %} 、 {% block css %} {% endblock %}
3、注意继承的顺序,就像打补丁,我们看到的都是最上面一层补丁,即覆盖现象
← 模块层之标签、自定义标签 模型层 →