Python—Django中的模板(template)

作者:BerenCamlost

1 定义模板

1.1 变量

  • 视图传递给模板的数据
  • 要遵守标识符规则
  • 语法 {{var}}(var代表变量)
  • 【注意】:如果使用的变量不存在,则插入的是空字符串
  • 在模板中使用点语法,点后边的东西按如下顺序进行匹配
    • 字典查询
    • 属性或者方法
    • 数字索引

在模板中调用方法

  1. sunck/models.py:
# 插入到Students类中的方法
def get_name(self):
    return self.sname
  1. sunck/views.py:
# templates 测试
def templates(request):
    stu = Students.stuObj2.get(sname='刘德华')
    return render(request, 'sunck/templates测试/templates1.html', {'stu': stu})
  1. sunck/urls.py:
    path('template/', views.templates),
  1. sunck/templates测试/templates.html:
<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <title>模板测试</title>
</head>
<body>
<h1>{{ stu.get_name }}</h1>
<h1>{{ stu.sname }}</h1>

</body>
</html>
  1. 效果:
    刘德华
  • 【注意】:在模板中调用方法时不能传递参数

1.2 标签

1.2.1 语法

{% tag %}

1.2.2 作用

  1. 在输出中创建文本
  2. 控制逻辑和循环

1.2.3 if

  1. 格式:
<!--if语句-->
{% if 表达式 %}
    语句
{% endif %}

<!--else语句-->
{% if 表达式 %}
    语句1
{% else %}
    语句2
{% endif %}

<!--else if语句-->
{% if 表达式1 %}
    语句1
{% elif 表达式2 %}
    语句2
    ·
    ·
    ·
{% elif 表达式n %}
    语句n
{% else %}<!--可有可无-->
    语句e
{% endif %}
  1. 举例
<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <title>模板测试</title>
</head>
<body>
    <h1>{{ stu.get_name }}</h1>
    <h1>{{ stu.sname }}</h1>

    <h1>num={{ num }}</h1>
    {% if num is 10 %}
    <h2>You are a handsome boy</h2>
    {% elif num is 20 %}
        <h2>you are a Very handsome boy</h2>
    {% else %}
        <h2>You are not a handsome boy</h2>
    {% endif %}
</body>
</html>

在Views.py中给num传一个数字,得到效果如下图所示:
2

1.2.4 for

{% for 变量 in 列表 %}
{#语句1#}
{% empty %}
{#语句2#}
{% endfor %}
  • 【注意】:当列表为空或者不存在时,执行empty语句,empty可有可无
  • {{ forloop.counter }}表示循环次数,可以用在for语句中,例如:
    <ul>
        {% for student in stu1 %}
        {#语句1#}
            <li>{{ forloop.counter }}:{{ student.sname }}---{{ student.scontend }}</li>
        {% empty %}
        {#语句2#}
            <li>没有学生信息</li>
        {% endfor %}
    </ul>
  • views.py文件中为:
def templates(request):
    stu1 = Students.stuObj2.all()
    # stu1 = Students.stuObj2.filter(sname__startswith="刘")
    # stu1 = Students.stuObj2.filter(sname__startswith="Liu")
    return render(request, 'sunck/templates测试/templates1.html', { 'stu1': stu1})

1.2.5 comment

  • 格式
{% commnet %}
    被注释的内容
{% endcomment %}
  • 作用:相当于多行注释,被注释的内容不再执行

1.2.6 ifequal/ifnotequal

  • 【作用】:判断是否相等或者不相等
  • 【格式】:
{% ifequal 值1 值2 %}
    语句1
{% endifequal %}  # 如果值1等于值2,执行语句1,否则不执行语句1

1.2.7 include

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

1.2.8 url

  • 【作用】:反向解析
  • 【格式】:{% url 'namespace: name' p1 p2 %}

1.2.9 csrf_token

  • 【作用】:用于跨站请求伪造保护
  • 【格式】:{% csrf_token %}

1.2.10 block, extends

  • 【作用】:用于模板的继承

1.2.11 autoescape

  • 【作用】:用于HTML转义

1.3 过滤器

  • 【语法】:{{var|过滤器}}
  • 【作用】:在变量被显示前修改它,只是加一个效果,对变量不会造成影响

1.3.1 upper/lower

  • 大写和小写,示例:
{#5. 过滤器#}
<h1>原型:{{ str }}</h1>
<h1>upper:{{ str|upper }}</h1>
<h1>lower:{{ str|lower}}</h1>
  • 【效果】:
    效果

1.3.2 过滤器可以传递参数

  • 下面以var|join:'str'为例解释传参的过程:
# templates 测试
def templates(request):
    stu1 = Students.stuObj2.all()
    return render(request, 'sunck/templates测试/templates1.html', {'stu1': stu1,})
<h2>{{ stu1|join:"--的儿子是-->" }}</h2>

【效果】(涉及隐私我打了马赛克):
效果

1.3.3 default默认值

  • 如果一个变量没有被提供,或者值为false,空,我们可以通过 default 语法使用默认值
  • 【示例】:<h2>{{ stu1.sname|default:'啥都么的' }}</h2>

1.3.4 date

  • 【作用】:根据给定格式转换日期为字符串
  • 【示例】:{{dateVal|date:'y-m-d'}}
    以年月日的形式显示日期,dateVal是一个日期变量

1.3.5 escape

  • 【作用】:HTML转义

1.3.6 加减乘除

  • 【示例】:
<ul>
    <li>num:{{ num }}</li>
    <li>num+10:{{ num|add:10 }}</li>
    <li>num-5:{{ num|add:-5 }}</li>
    <!--num/1*5-->
    <li>num*5:{% widthratio num 1 5 %}</li>
    <li>num/2:{% widthratio num 2 1 %}</li>
</ul>
  • 效果:
    效果

1.3.7 给之前的学生列表加背景颜色

  • |divisibleby:2:可被2整除
<ul>
    {% for student in stu1 %}
        {% if forloop.counter|divisibleby:2 %}
            <li style="background-color: gray">{{ forloop.counter }}:{{ student.sname }}---{{ student.scontend }}</li>
        {% else %}
            <li style="color: orange">{{ forloop.counter }}:{{ student.sname }}---{{ student.scontend }}</li>
        {% endif %}
    {% empty %}
        <li>没有学生信息</li>
    {% endfor %}
</ul>
  • 【效果】(打码真的费时间):
    效果

1.4 注释

  • 【单行注释】:{{# #}}
  • 【多行注释】:{%comment%}....{%endcomment%}

2 反向解析

2.1 作用

即使url变动,也可以根据namespace和name反向解析出正确的域名,从而实现超链接的正确执行。

2.2 示例

<a href="{% url 'sunck:good' %}">反解析连接good</a>
# project/project/urls.py
urlpatterns = [
    path('sunck/', include('sunck.urls', namespace="sunck")),
]
# project/sunck/urls.py
urlpatterns = [
    path('template/good/', views.good, name='good'),
]

2.3 传入参数

模板:

<a href="{% url 'sunck:good' 1 %}">反解析连接good</a>

url:

path('template/good/<int:id>', views.good, name='good'),

views视图:

# templates-反向解析 测试
def good(request, id):
    return render(request, 'sunck/templates测试/good.html', {'num': id})

good模板:

<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <title>good</title>
</head>
<body>
    <h1>good--{{ num }}</h1>
</body>
</html>

3 模板继承

3.1 作用

  • 模板继承可以减少页面的重复定义,实现页面的重用

3.2 block标签

  • 【作用】:在父模板中预留区域 ,子模板去填充
  • 【语法】:
{% block 标签名 %}
...
{% endblock 标签名 %}

3.3 extends标签

  • 继承模板,需要写在模板文件的第一行
  • 【语法】:
{% extends 'myApp/base.html(父模板路径)' %}
{% block 标签名 %}
内容
{% endblock 标签名 %}

3.4 示例

  • base.html:
<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <title>base</title>
</head>
<body>
    <div id="header">
        <h1>header</h1>
    </div>
    <div id="main">
        {% block main %}

        {% endblock main %}
    </div>
    <div id="footer">
        <h1>footer</h1>
    </div>

</body>
</html>
  • main.html:
{% extends "sunck/模板继承/base.html" %}
{% block main%}
    <h1>{{ 'main'|upper }}</h1>
{% endblock main %}

4 HTML转义

4.1 问题

# templates 测试
def templates(request):
    return render(request, 'sunck/templates测试/templates1.html',
                  {
                   'str2': '<h1>HTML转义</h1>'
                   })
{#6 HTML转义#}
{{ str2 }}
  • 这时的输出为<h1>HTML转义</h1>,未经过渲染,而我们想要的输出是

    HTML转义

4.2 解决

  • 过滤器safe可以关闭转义,escape开启转义
  • 标签{% autoescape off %}...{% endautoescape %}关闭自动转义,将off变成on开启自动转义

4.3 示例

  • html文件:
{#6 HTML转义#}
{{ str2 }}
{{ str2|escape }}
{{ str2|safe }}
{% autoescape on %}
    1{{ str2 }}
    2{{ str2 }}
{% endautoescape %}
{% autoescape off %}
    1{{ str2 }}
    2{{ str2 }}
    3{{ str2 }}
{% endautoescape %}
  • 【效果】:
    效果

5 CSRF

5.1 跨站请求伪造

某些恶意网站包含链接,表单,按钮,js,利用登录用户在浏览器中认证,从而攻击服务

5.2 防止CSRF

  1. 在settings.py文件的MIDDLEWARE增加'django.middleware.csrf.CsrfViewMiddleware'
    在这里插入图片描述
  2. 上述方法会将所有的跨站请求屏蔽,为了允许自身的跨站请求服务,应该在HTML页面中加入{% csrf_token %},如:
<form action="../register/" method="post">
    {% csrf_token %}
    <!--这里的action需要和后面的urls路径相对应-->
    姓名:<input type="text" name="name" value=""/>
    <hr>
    性别:<input type="radio" name="gender" value="1"><input type="radio" name="gender" value="0"><hr>
    年龄:<input type="text" name="age" value=""/>
    <hr>
    爱好:<input type="checkbox" name="hobby" value="power"/>权利<input type="checkbox" name="hobby" value="money">金钱<input type="checkbox" name="hobby" value="beauty">美女<input type="checkbox" name="hobby" value="Tesla">Tesla
    <hr>
    <input type="submit" value="注册">
</form>

6 验证码

6.1 作用

  • 在用户注册,登录页面的时候使用,为了防止暴力请求,减轻服务器的压力
  • 是防止CSRF的一种方式

6.2 源码及效果

6.3 输入验证码

6.3.1 视图

def verifi_code(request):
    return render(request, 'sunck/templates测试/verificationcode.html', )


# 展示结果
def show(request):
    code = request.POST.get('code')
    right_code = request.session['verification_code']
    if code.upper() == right_code.upper():
        return HttpResponse('对了!'+right_code)
    else:
        return HttpResponse('错了!'+code+'----'+right_code)

6.3.2 url

    path('VerificationCode/code', VerificationCode.verification_code),
    path('VerificationCode/', VerificationCode.verifi_code),
    path('VerificationCode/show', VerificationCode.show, name='show'),

6.3.3 模板

<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <title>验证码</title>
</head>
<body>
    <h3>请输入验证码</h3>
    <form method="post" action="{% url 'sunck:show' %}">
        {% csrf_token %}
        <input type="text" name="code" value=""/>
        <img src="/sunck/VerificationCode/code">
        <hr>
        <input type="submit" value="登录"/>
    </form>
</body>
</html>

猜你喜欢

转载自blog.csdn.net/weixin_43830248/article/details/86654302