# 模版语法
# 模板组件和母版继承
- 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、注意继承的顺序,就像打补丁,我们看到的都是最上面一层补丁,即覆盖现象
← 模块层之标签、自定义标签 模型层 →