Django-模板

概述

  • 模板由两部分组成:
    • HTML代码
    • 逻辑控制代码:
      • 变量
      • 标签
      • 过滤器
  • 作用:很便利的生成HTML
  • 优点:模板的设计实现了业务逻辑与显示的分离,一个视图可以使用任意的模板,一个模板可以被多个视图使用
  • 模板的处理:
    • 加载:根据给定的标识找到对应的模板然后预处理,通常将它编译好放到到内存中
    • 渲染:使用context属性的数据插入模板形成新的字符串

定义模板

  • 使用前提

    • 在工程目录下创建名为templates的目录,在settings.py文件中配置templates目录的路径

      1
      2
      3
      4
      5
      6
      7
      8
      9
      10
      11
      12
      13
      14
      15
      TEMPLATES = [
      {
      'BACKEND': 'django.template.backends.django.DjangoTemplates',
      'DIRS': [os.path.join(BASE_DIR, 'templates')],
      'APP_DIRS': True,
      'OPTIONS': {
      'context_processors': [
      'django.template.context_processors.debug',
      'django.template.context_processors.request',
      'django.contrib.auth.context_processors.auth',
      'django.contrib.messages.context_processors.messages',
      ],
      },
      },
      ]
  • 变量

    • 语法:
      1
      {{ var }}
    • 要遵守标识符规则
    • 在模板中使用点语法,按照顺序查询:
      • 字典查询
      • 属性或者方法查询
      • 数字索引查询
    • 如果使用的变量不存在,则插入空字符串
    • 在模板中调用对象的方法:
      1
      2
      3
      4
      5
      6
      7
      8
      9
      10
      11
      12
      13
      <body>
      <h1>{{ num }}</h1>
      <h1>{{ flag }}</h1>
      <h1>{{ string }}</h1>
      <h1>{{ stu.name }}</h1>
      <h1>*{{ hobby }}*</h1>
      <h1>{{ stu.run }}</h1>
      <ul>
      {% for item in stus %}
      <li>{{ item.name }}--{{ item.grade }}--{{ item.age }}</li>
      {% endfor %}
      </ul>
      </body>

      注意:调用函数不能传递参数

  • 标签

    • 语法:
      1
      {% tag %}
    • 作用:
      • 在输出中创建文本
      • 控制循环或逻辑
      • 加载外部信息到模板中供以后的变量使用
  • if

    • 格式:

      1
      2
      3
      {% if 表达式 %}
      语句
      {% endif %}
      1
      2
      3
      4
      5
      {% if 表达式 %}
      语句1
      {% else %}
      语句2
      {% endif %}
      1
      2
      3
      4
      5
      6
      7
      8
      {% if 表达式1 %}
      语句1
      {% elif 表达式2 %}
      语句2
      ……
      {% else %}
      语句e
      {% endif %}
    • 示例:

      1
      2
      3
      {% if num > 15 %}
      <h1>sunck is a good man</h1>
      {% endif %}
  • for

    • 格式:

      1
      2
      3
      {% for 变量 in 集合 %}
      语句
      {% endfor %}
      1
      2
      3
      4
      5
      {% for 变量 in 集合 %}
      语句
      {% empty %}
      如果给出的集合为空或者集合不存在则执行这里
      {% endfor %}
    • 示例:

      1
      2
      3
      4
      5
      6
      7
      <ul>
      {% for item in stus1 %}
      <li>{{ item.name }}--{{ item.grade }}--{{ item.age }}</li>
      {% empty %}
      <h1>没有学生</h1>
      {% endfor %}
      </ul>
  • comment

    • 多行注释
    • 格式:
      1
      2
      3
      {% comment %}
      多行注释
      {% endcomment %}
  • ifequal/ifnotequal

    • 格式:

      1
      2
      3
      {% ifequal 值1 值2 %}
      语句
      {% endifequal %}

      值1等于值2则执行语句

      1
      2
      3
      {% ifnotequal 值1 值2 %}
      语句
      {% endifnotequal %}

      值1不等于值2才执行语句

  • inluce

    • 作用:加载模板并以标签内的参数渲染
    • 格式:
      1
      {% include "模板目录" %}
  • url

    • 作用:反向解析
    • 格式:
      1
      {% url "namespace:name" 参数1 …… %}
  • csrf_token

    • 作用:用于跨站请求伪造保护
    • 格式:
      1
      {% csrf_token %}
  • block、extends

    • 作用:继承
  • autoescape

    • 作用:用于HTML转义
  • 过滤器

    • 语法:
      1
      {{ 变量|过滤器 }}
    • 作用:在变量被显示前修改它的显示
  • lower

    • 转小写:
      1
      <h1>{{ string|lower }}</h1>
  • upper

    • 转大写:
      1
      <h1>{{ string|upper }}</h1>
  • title

    • 字母的首字符大写:
      1
      <h1>{{ string|title }}</h1>
  • join

    • 将列表拼接成字符串
    • 过滤器可以传递参数
      1
      <h1>{{ hobby|join:"," }}</h1>
  • default

    • 如果变量没有被提供,或者值为False或空,则使用默认值,否则使用变量给定的值
      1
      <h1>{{ age|default:1 }}</h1>
  • date

    • 根据给定的格式化的规则格式化date变量
      1
      <h1>{{ value|date:"Y-m-d" }}</h1>
  • escape

    • 开启HTML 转义
  • safe

    • 关闭转义
  • add

    • 加法或减法
      1
      2
      <h1>{{ num|add:2 }}</h1>
      <h1>{{ num|add:-2 }}</h1>
  • 乘除

    • 无法用过滤器实现
    • 用标签实现
      1
      2
      3
      4
      {# widthratio arg1 arg2 arg3   #}
      {# arg1/arg2*arg3 #}
      <h1>{% widthratio num 1 2 %}</h1>
      <h1>{% widthratio num 2 1 %}</h1>
  • 自定义过滤器

    • 过滤器就是python中的函数,可以注册函数后在模板中当过滤器使用
    • 在应用目录下创建名为templatetags的包
    • templatetags目录下创建名为filters.py的文件
      1
      2
      3
      4
      5
      6
      7
      8
      9
      10
      11
      12
      # -*- coding:utf-8 -*-

      #导入Library库
      from django.template import Library

      #创建一个Library对象
      register = Library()

      #使用装饰器进行注册过滤器
      @register.filter
      def mod(value):
      return value % 2 == 0
      1
      2
      3
      @register.filter
      def mod(value, num):
      return value % num == 0
    • 在模板中引入(如果无效重启应用即可)
      1
      2
      3
      4
      {% load filters %}
      {% if 9|mod %}
      <h1>sunck is a nice man</h1>
      {% endif %}

反向解析

  • 主路由:

    1
    url(r'^', include('myApp.urls', namespace="sunck")),
  • 子路由:

    1
    url(r'^t3test1/(\d+)/$', views.t3test, name="t3test"),
  • 链接代码:

    1
    <a href="{% url 'sunck:t3test' 5 %}">点我跳转</a>

HTML转义

  • 默认开启转义:不解析,解析成普通字符串

  • 关闭转义:开启解析,有些被解析成HTML标签

    1
    2
    3
    4
    5
    def t4(request):
    test1 = "<script type='text/javascript'>alert('autoescape off:关闭转义')</script>"
    test2 = "<h1>escape:开启转义</h1>"
    test3 = '<h1>safe:关闭转义</h1>'
    return render(request, 'myApp/t4.html', {'string1': test1, 'string2': test2, 'string3': test3})
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    19
    20
    21
    22
    23
    <!DOCTYPE html>
    <html lang="en">
    <head>
    <meta charset="UTF-8">
    <title>转义</title>
    </head>
    <body>
    {#autoescape off:关闭转义#}
    {#autoescape on:开启转义#}
    {# {% autoescape off %}#}
    {# {{ string1 }}#}
    {# {% endautoescape %}#}

    {#escape:开启转义#}
    {# {% autoescape off %}#}
    {# {{ string1 }}#}
    {# {{ string2|escape }}#}
    {# {% endautoescape %}#}

    {#safe:关闭转义#}
    {{ string3|safe }}
    </body>
    </html>

跨站请求伪造

  • 某些恶意的网站上包含链接、表单按钮或者JavaScript,他们会利用登陆过的用户认证信息试图在你的网站上完成某些操作,这就是跨站攻击。

  • 防止csrf:

    • settings.py中启用'django.middleware.csrf.CsrfViewMiddleware',中间件,此项在创建工程时就默认启用
  • 验证表单:

    1
    {% csrf_token %}

    1.在客户端存入一个名为csrftoken的cookie
    2.给表单增加一个隐藏域,value值为名为scrftoken的cookie的键进行的加密

继承

  • 作用:模板的继承可以减少页面的重复定义,实现页面的重用
  • 实现:
    • block 标签:在父模板中预留区域,在子模板中填充
    • extends 标签:继承,写在模板的第一行
  • 示例:
    • 父模板:
      1
      2
      3
      4
      5
      6
      7
      8
      9
      10
      11
      12
      13
      14
      15
      16
      17
      18
      19
      <!DOCTYPE html>
      <html lang="en">
      <head>
      <meta charset="UTF-8">
      <title>{% block title %}{% endblock title %}</title>

      {% block link %}{% endblock link %}

      {% block script %}{% endblock script %}
      </head>
      <body>
      <header>头部</header>
      <div>
      {% block main %}
      {% endblock main %}
      </div>
      <footer>尾部</footer>
      </body>
      </html>
    • 子模板:
      1
      2
      3
      4
      5
      6
      7
      8
      9
      10
      11
      {% extends 'myApp/base.html' %}

      {% block title %}主页{% endblock title %}

      {% block link %}{% endblock link %}

      {% block script %}{% endblock script %}

      {% block main %}
      <h1>home</h1>
      {% endblock main %}

静态文件

  • 包含项目中的css、js、图片、json等文件
  • 在工程目录创建名为static的目录作为静态文件的存放位置
  • 配置settings.py文件:
    1
    2
    3
    4
    STATIC_URL = '/static/'
    STATICFILES_DIRS = [
    os.path.join(BASE_DIR, "static"),
    ]
  • 使用:
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    {% load static from staticfiles %}
    {#{% load static %}#}
    <!DOCTYPE html>
    <html lang="en">
    <head>
    <meta charset="UTF-8">
    <title>首页</title>
    {# <link rel="stylesheet" type="text/css" href="/static/css/index.css" />#}
    <link rel="stylesheet" type="text/css" href="{% static 'css/index.css' %}"/>
    </head>
    <body>
    <h1>sunck is a good man</h1>
    </body>
    </html>