django之模板层

什么是模板层

模板层是在视图函数中被用作渲染的html文件,后端中的数据常常需要动态的传递到前端中。后端我们使用的python语法,而前端使用的是html语言。我们知道想让前端数据传递到后端,只需将数据在GET或者POST中携带。那后端如何将数据传递到前端呢?

我们在视图层可以将HttpResponse或者JsonResponse直接将数据进行返回,但这不能满足前端胡里花哨的页面显示。

有没有可能先制作好html文件,然后在其中预留一些位置,我们后端再将数据填入这些空白中呢?

答案是肯定的。这就是django中的模板层,当然我们得遵循模板层特有的语法。

1.模板语法符号

{{ }}:变量相关

{% %}:逻辑相关

python基本数据类型全部支持传递给html文件。

views.py
-------------------
def index(request):
    my_dict = {
        'user': 'yyh',
        'password': 123,
        'age': 18
    }
    return render(request, 'index.html', {'my_dict': my_dict})
	# return render(request,'index.html',locals()) locals()会将函数命名空间内的所有变量名全部传递到index.html中
index.html
-------------------------------
<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <title>Title</title>
    <script src="https://cdn.bootcss.com/jquery/3.4.1/jquery.js"></script>
</head>
<body>
<p>{{ my_dict }}</p>
<p>{{ my_dict.user }}</p>
<p>{{ my_dict.password }}</p>
{% for key in my_dict %}
    {{ key }}
    {{ my_dict.key }}
{% endfor %}
    
{% for key,value in my_dict.items %}
    {{ key }}
    {{ value }}
{% endfor %}
<br>
{{ my_dict.hobbies.1.1 }}
    
{# my_dict.values my_dict.items #}
</body>
</html>

可以看到只能模板语法不管是列表还是字典都只能通过 . 的方式取值。

2.模板语法之过滤器

|length
|add
|default
|truncatechars
|truncatewords
|filesizeformat
|slice
|date
|safe
<p>过滤器  |左边的会当做过滤器的第一个参数 过滤器名右边的会当做过滤器的第二个参数</p>
<p>求数据长度:{{ s|length }}</p>
<p>加法运算:{{ n|add:10 }}、{{ s|add:13132 }}、{{ s|add:'DSB' }}</p>
<p>默认值(判断值是否为空):{{ b|default:'这个b布尔值是True' }}、{{ ff|default:'这个ff布尔值是Flase' }}</p>
<p>截取字符(截取5个字符 三个点也算):{{ s|truncatechars:8 }}</p>
<p>截取单词(截取8个单词 三个点不算):{{ ss|truncatewords:8 }}、{{ sss|truncatewords:4 }}</p>
<p>文件大小:{{ file_size|filesizeformat }}</p>
<p>切片操作:{{ s|slice:'0:2' }}、{{ s|slice:"0:8:2" }}</p>
<p>日期格式化:{{ ddd|date:'Y年/m月/d日' }}</p>
<p>转义:{{ res|safe }}、{{ res1 }}、后端直接标识安全:{{ res2 }}</p>

3.前后端取消转义

后端
----------
def login(request):
    s = '<h1>hello world</h1>'
    return render(request,'login.html',locals())

前端
-------
<body>
{{ s }}
</body>
---------# 浏览器将显示'<h1>hello world</h1>'

----------
<body>
{{ s|safe }}
</body>
----------   # 浏览器将以h1渲染helloworld

取消转义可以在前端完成,也可以在后端完成

from django.utils.safestring import mark_safe
def login(request):
    s = '<h1>hello world</h1>'
    s = mark_safe(s)
    return render(request, 'login.html', locals())


----------------
<body>
{{ s }}
</body>

4.模板语法之标签

{% for foo in l %}
    <p>{{ forloop }}</p>
{% endfor %}


{'parentloop': {}, 'counter0': 0, 'counter': 1, 'revcounter': 6, 'revcounter0': 5, 'first': True, 'last': False}

{'parentloop': {}, 'counter0': 1, 'counter': 2, 'revcounter': 5, 'revcounter0': 4, 'first': False, 'last': False}

{'parentloop': {}, 'counter0': 2, 'counter': 3, 'revcounter': 4, 'revcounter0': 3, 'first': False, 'last': False}

{'parentloop': {}, 'counter0': 3, 'counter': 4, 'revcounter': 3, 'revcounter0': 2, 'first': False, 'last': False}

{'parentloop': {}, 'counter0': 4, 'counter': 5, 'revcounter': 2, 'revcounter0': 1, 'first': False, 'last': False}

{'parentloop': {}, 'counter0': 5, 'counter': 6, 'revcounter': 1, 'revcounter0': 0, 'first': False, 'last': True}

模板语法中的for循环自带有一个forloop的对象,可以通过使用这个对象对for循环进行一些处理。

{% for foo in l %}
    {% if forloop.first %}
        <p>第一次循环噢</p>
    {% elif forloop.last %}
        <p>最后一次循环哦</p>
    {% else %}
        <p>{{ foo }}</p>
    {% endif %}
{#    在l为空时执行#}
    {% empty %}
    <p>haa</p>
    <p>haa</p>
{% endfor %}

# 可用add来判断第几次循环
{% for foo in l %}
    {% if forloop.counter|add:-2 %}
        {{ foo }}
    {% endif %}
{#    在l为空时执行#}
    {% empty %}
    <p>haa</p>
{% endfor %}
</body>
</html>

5.自定义过滤器

自定义过滤器 标签 inclusion_tag
先完成以下前期准备工作
1.在应用名下新建一个名字必须叫templatetags文件夹
2.在该文件夹内新建一个任意名称的py文件(eg:mytag)
3.在该文件内 必须先写以下两句代码
from django.template import Library

register = Library()

# 自定义过滤器
@register.filter(name='my_sum')
def index(a,b):
    return a + b


# 自定义标签
@register.simple_tag(name='my_baby')
def xxx(a,b,c,d):
    return '%s?%s?%s?%s'%(a,b,c,d)


# 自定义inclusion_tag
@register.inclusion_tag('demo.html',name='myin')
def index1(n):
    l = []
    for i in range(n):
        l.append(i)
        # 将列表传递给demo.html
        # return locals()
        return {'l':l}
<p>自定义过滤器的使用</p>
{% load mytag %}
<p>{{ 10|my_sum:90 }}</p>

<p>自定义标签的使用</p>
{% load mytag %}
<p>{% my_baby 1 2 3 'hello world' %}</p>


<p>自定义的过滤器可以在逻辑语句中而自定义的标签不可以</p>
{% if 10|my_sum:100 %}
<p>条件成立</p>
{% endif %}

{% if my_baby 1 2 3 4 %}
<p>条件成立</p>
{% endif %}

<p>自定义inclusion_tag的使用</p>
{% load mytag %}
{% myin 5 %}
# 总结 页面上使用他们 统一先导入
{% load mytag %}

6.模板的继承

模板的继承实际上是在一个html模版上用 {% block 名字%}{% endblock %}

来划分一块区域。其他的html模板可以通过{% extends 'index.html' %},然后

{% block 名字%}{% endblock %}可以继承index.html里的代码,并将自己的block填充。{{block.super}}可以调用父页面对应区域的内容(在哪个block下使用就调用哪一块)

index.html

<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <title>Title</title>
    <script src="https://cdn.bootcss.com/jquery/3.4.1/jquery.js"></script>
    <link href="/static/bootstrap-3.3.7-dist/css/bootstrap.css" rel="stylesheet">
    <script src="/static/bootstrap-3.3.7-dist/js/bootstrap.js"></script>
    {% block css %}

    {% endblock %}
</head>
<body>
{# 导航条样式 #}
<nav class="navbar navbar-inverse">
  <div class="container-fluid">
    <!-- Brand and toggle get grouped for better mobile display -->
    <div class="navbar-header">
      <button type="button" class="navbar-toggle collapsed" data-toggle="collapse" data-target="#bs-example-navbar-collapse-1" aria-expanded="false">
        <span class="sr-only">Toggle navigation</span>
        <span class="icon-bar"></span>
        <span class="icon-bar"></span>
        <span class="icon-bar"></span>
      </button>
      <a class="navbar-brand" href="#">Brand</a>
    </div>

    <!-- Collect the nav links, forms, and other content for toggling -->
    <div class="collapse navbar-collapse" id="bs-example-navbar-collapse-1">
      <ul class="nav navbar-nav">
        <li class="active"><a href="#">Link <span class="sr-only">(current)</span></a></li>
        <li><a href="#">Link</a></li>
        <li class="dropdown">
          <a href="#" class="dropdown-toggle" data-toggle="dropdown" role="button" aria-haspopup="true" aria-expanded="false">Dropdown <span class="caret"></span></a>
          <ul class="dropdown-menu">
            <li><a href="#">Action</a></li>
            <li><a href="#">Another action</a></li>
            <li><a href="#">Something else here</a></li>
            <li role="separator" class="divider"></li>
            <li><a href="#">Separated link</a></li>
            <li role="separator" class="divider"></li>
            <li><a href="#">One more separated link</a></li>
          </ul>
        </li>
      </ul>
      <form class="navbar-form navbar-left">
        <div class="form-group">
          <input type="text" class="form-control" placeholder="Search">
        </div>
        <button type="submit" class="btn btn-default">Submit</button>
      </form>
      <ul class="nav navbar-nav navbar-right">
        <li><a href="#">Link</a></li>
        <li class="dropdown">
          <a href="#" class="dropdown-toggle" data-toggle="dropdown" role="button" aria-haspopup="true" aria-expanded="false">Dropdown <span class="caret"></span></a>
          <ul class="dropdown-menu">
            <li><a href="#">Action</a></li>
            <li><a href="#">Another action</a></li>
            <li><a href="#">Something else here</a></li>
            <li role="separator" class="divider"></li>
            <li><a href="#">Separated link</a></li>
          </ul>
        </li>
      </ul>
    </div><!-- /.navbar-collapse -->
  </div><!-- /.container-fluid -->
</nav>
<div class="container-fluid">
    <div class="row">
        <div class="col-md-3">
            <div class="list-group">
                 {% block list_style %}
                  <a href="/index/" class="list-group-item active" id="id_index">
                    首页
                  </a>
                  <a href="/login/" class="list-group-item" id="id_login">登录</a>
                  <a href="/register/" class="list-group-item" id="id_register">注册</a>
                 {% endblock %}
            </div>
        </div>
        <div class="col-md-9">
            <div class="panel panel-default">
              <div class="panel-heading">
                <h3 class="panel-title">Panel title</h3>
              </div>
              <div class="panel-body panel-primary">
                  {% block content %}

                  {% endblock %}
{#                <div class="jumbotron">#}
{#                  <h1>Hello, world!</h1>#}
{#                  <p>...</p>#}
{#                  <p><a class="btn btn-primary btn-lg" href="#" role="button">Learn more</a></p>#}
{#                </div>#}
              </div>
            </div>
        </div>
    </div>
</div>
{% block js %}
    <script>
        $('#id_index').addClass('active').siblings().removeClass('active')
    </script>
{% endblock %}
</body>
</html>

login.html

{% extends 'index.html' %}
{#{% block list_style %}#}
{#<a href="/index/" class="list-group-item">#}
{#首页#}
{#</a>#}
{#<a href="/login/" class="list-group-item active">登录</a>#}
{#<a href="/register/" class="list-group-item">注册</a>#}
{#{% endblock %}#}

{% block css %}
    <style>

    </style>
{% endblock %}


{% block content %}
    <h1 class="text-center">登录</h1>
    <p>用户名:<input type="text"></p>
    <p>密码:<input type="password"></p>
    <button class="btn btn-danger">提交</button>
{% endblock %}

{% block js %}
    <script>
        $('#id_login').addClass('active').siblings().removeClass('active')
    </script>
{% endblock %}

7.模板的导入

django还支持将html页面当做模块使用,哪里需要导哪里,被导入的这个html文件通常是不完整的。

{% include 'left.html' %}

posted @ 2020-01-07 20:55  GhostAnt  阅读(189)  评论(0编辑  收藏  举报