Django 2.0 学习(13):Django模板继承和静态文件

Django模板继承和静态文件

模板继承(extend)

Django模板引擎中最强大也是最复杂的部分就是模板继承了,模板继承可以让我们创建一个基本的"骨架"模板,它可以包含网页中的全部元素,并且可以定义能够被子模板覆盖的blocks。为了容易理解模板继承,我们先写一个模板:

<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <title>{% block title %}Replaceable template{% endblock %}</title>
</head>
<body>
    <div id="sidebar">
        {% block sidebar %}
        <ul>
            <li><a href="/">Home</a> </li>
            <li><a href="/blog">Blog</a> </li>
        </ul>
        {% endblock %}
    </div>
    
    <div id="content">
        {% block content %}{% endblock %}
    </div>
</body>
</html>

这个模板,我们把它叫做base.html,它定义了一个可以用于两列排版页面的简单HTML骨架。"子模板"可以用它们的内容填充空白的blocks。在这个例子中,block标签定义了三个可以被子模板内容填充的block,block告诉模板引擎:子模板可能会覆盖掉模板中的这些位置。

接下来,我们再写一个子模板:

{% extends "polls/base.html" %}        # 模板路径根据项目或者app的路径来写,笔者这里的模板位于app中

{% block title %}Child template{% endblock %}

{% block content %}
    {% for entry in blog_entries %}
        <h3>{{ entry.title }}</h3>
        <p>{{ entry.body }}</p>
    {% endfor %}
{% endblock %}

extends标签是这里的关键,它告诉模板引擎这个模板继承了另一个模板。当模板系统处理这个模板时,首先定位父模板--此例中,就是"base.html"。那时模板引擎注意到base.html中的三个block标签,并用子模板中的内容来替换这些block。根据blog_entries的值,子模板输出的内容会是下面的内容:

<!DOCTYPE html>
<html lang="en">
<head>
    <link rel="stylesheet" href="style.css" />
    <title>Child template</title>
</head>
 
<body>
    <div id="sidebar">
        <ul>
            <li><a href="/">Home</a></li>
            <li><a href="/blog/">Blog</a></li>
        </ul>
    </div>
 
    <div id="content">
        <h2>Entry one</h2>
        <p>This is my first entry.</p>
 
        <h2>Entry two</h2>
        <p>This is my second entry.</p>
    </div>
</body>
</html>

注意:子模板并没有定义sidebar block,所以系统使用了父模板中的值。父模板的{% block %}标签中的内容总是被用作备选内容。这种方式使代码得到最大程度的复用,并且使得添加内容到共享的内容区域更加简单,例如:部分范围内的导航。

说明:

1.如果在模板中使用{% extends %}标签,它必须是模板中的第一个标签,其他的任何情况下,模板继承都将无法工作;
2.在base模版中设置越多的 {% block %} 标签越好。请记住,子模版不必定义全部父模版中的block,所以,我们可以在大多数>block中填充合理的默认内容,然后,只定义我们需要的那一个。多一点钩子总比少一点好;
3.如果发现我们在大量的模板中复制内容,那就意味着我们应该把内容移动到父模板中的一个{% block %}中;
4.有时候,想在父模板的基础上再添加点其他的,而不是完全覆盖父模板的内容,那么我们只需要在想要填充的块里,再加上 >{{ block.super }}语句,我们就可以把父模板里的东西给留下来,如:

父模板中的
{% block title %}Parent template{% endblock %}

如果我们只想子模板的结果是在后面添加一个!,则只需要在子模板中写成
{% block title %}
    {{ block.super }}!
{% endblock %}

5.为了更好的可读性,也可以给我们的 {% endblock %} 标签一个 名字 。例如:

{% block content %}
...
{% endblock content %} 

6.在大型模板中,这个方法可以帮助我们清楚的看到哪个 {% block %}标签被关闭了;

最后,请注意我们不能在一个模版中定义多个相同名字的 block 标签。这个限制的存在是因为block标签的作用是“双向”的。这个意思是,block标签不仅提供了一个坑去填,它还在父模版中定义了填坑的内容。如果在一个模版中有两个名字一样的 block 标签,子模版的父模版将不知道使用哪个block的内容。

注意:模板一般放在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/ 目录下面。这样在使用的时候,有app作为名称的一部分,就不会混淆。

模板include

假如我们有以下模板index.html,代码:

<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <title>Title</title>
</head>
<body>

<div>网页公共头部部分</div>

<h2> 网页body部分 </h2>

<div>网页公共底部部分</div>

</body>
</html>

做过web开发的同学都知道大部分网页的公共头部,公共底部部分代码每个页面都一样,那么就应该将其单独拿出做为一个html, 这样修改这部分代码时候,不需要每个页面都修改, 所以在django中我们可以这么做:
top.html

<div>网页公共头部部分</div>

bottom.html

<div>网页公共底部部分</div>

index.html

<!DOCTYPE html>  
<html lang="en">  
<head>  
    <meta charset="UTF-8">  
    <title>Title</title>  
</head>  
<body>  
  
{% include 'top.html' %}  
  
<h2> 网页body部分 </h2>  
  
{% include 'bottom.html' %}  
  
</body>  
</html>

我们可以使用Django模板引擎的include语法,来将单独的页面包含到当前模板页面中。有同学有疑问,那我们通过视图传递给模板的上下文,在被包含的模板中可以使用吗?可以直接使用,假如我们的视图函数如下:

def index(request):  
    return render(request, 'polls/index.html', {'a': 100, 'b': 200})

该Django视图函数,传递给模板并渲染模板。

top.html修改如下:

<div>网页公共头部部分:{{ a }}</div>      # 这样使用没有任何问题

我这里有这样的一个问题,假如所有的页面都使用共同的头部top.html, 可能针对1.html 2.html 3.html所使用的头部有些样式不一样,所需top.html:

<div classs='acss'>网页公共头部部分</div>  

但是对于5.html, 6.html使用的头部样式为:

<div class='bcss'>网页公共头部部分</div>  

很显然,如果直接通过include方式包含公共头部,会导致一些页面显示问题。既然部分参数不一样,include允许我们传递参数给被include的模板,我们可以使用with语法,那么问题解决如下:

{{ % include 'top.html' with mycss='acss' % }}  

top.html修改如下:

<div class='{{mycss}}'>网页公共头部部分</div> 

被包含模板中部分参数,由我们include的时候动态指定,那么top.html就不会因为细微差别而编写多份代码了。

静态文件配置

我们自己导入的一些页面相关的包就叫做静态文件

  • 在app目录中先创建static目录;
  • 在static目录里面导入我们的JS、CSS、Jquery和Bootstrap等;
  • 在项目settings.py中添加一些配置;
STATIC_URL = '/static/'   #这个配置就相当于下面配置的别名,如果这里的名字修改了就按照这里的名字去导入
STATICFILES_DIRS = [
    os.path.join(BASE_DIR,"static")  #E:day68static 找到static路径
]
  • 导入网页相关图片、CSS、JS、Jquery等
<link rel = "stysheet",href= "/static/index.css/"> 

<link rel="stylesheet" href="/static/bootstrap-3.3.7-dist/css/bootstrap.min.css">
原文地址:https://www.cnblogs.com/love9527/p/9082725.html