# 模版语法

# 模板组件和母版继承

  • 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、注意继承的顺序,就像打补丁,我们看到的都是最上面一层补丁,即覆盖现象