首页 > 代码库 > Django中模板总结[模板语言,模板继承,CSRF攻击,反向解析]

Django中模板总结[模板语言,模板继承,CSRF攻击,反向解析]

模板

概述

作为Web框架,Django提供了模板,用于编写html代码,还可以嵌入模板代码更快更方便的完成页面开发,再通过在视图中渲染模板,将生成最终的html字符串返回给客户端浏览器。模版致力于表达外观,而不是程序逻辑。模板的设计实现了业务逻辑view与显示内容template的分离,一个视图可以使用任意一个模板,一个模板可以供多个视图使用。

 

创建模板文件夹

  1. 在项目的文件里面定义一个templates文件夹
  2. 在创建的文件夹里面再创建一个文件夹为每个应用的html文件夹 起名为和应用名同名的文件名
  3. 去setting.py中添加配置一下文件路径 找到TEMPLATES项
 "DIRS":[os.path.jion(DASE_DIR, "templates")] 

 

模板包含两部分:

  • 静态部分,包含html、css、js。
  • 动态部分,就是模板语言。

Django处理模板分为两个阶段:

  • 1.加载:根据给定的路径找到模板文件,编译后放在内存中。
  • 2.渲染:使用上下文数据对模板插值并返回生成的字符串。

模板加载的过程

from django.template import loader, RequestContext
def index(request):
    """首页"""
    # 1.加载模板文件,得到一个模板对象
    temp = loader.get_template(‘booktest/index.html‘)
    # 2.定义模板上下文给模板传数据
    context = RequestContext(request, {‘kay‘: ‘kk‘})
    # 3.产生生标准的html内容
    res_html = temp.render(context)
    # 4.返回内容给浏览器
    return HttpResponse(res_html)
    -->简写
    return render(request, ‘booktest/index.html‘, {‘kay‘: ‘kaykay‘})

模板语言

变量

 

格式:

  • {{模板变量名}}

模板变量名是有数字,字母,下划线和点组成的,不能以下划线开头。
模板变量的解析顺序:

例如:book.title
  1. 把book当成一个字典,把title当成key,取值book[‘title’]
  2. 把book当成一个对象,把title当成属性,取值book.title
  3. 把book当成一个对象,把title当成方法名,取值book.title()
例如:book.0
  1. 把book当成一个字典,把0当成key,取值book[‘0’]
  2. 把book当成一个列表,把0当成下标,取值book[0]

注意:如果解析失败,则产生内容时用空字符串填充模板变量。

标签

语法如下:

{%代码段%}

for标签语法如下:

{%for item in 列表%}
循环逻辑
{{forloop.counter}}表示当前是第几次循环,从1开始
{%empty%}
列表为空或不存在时执行此逻辑
{%endfor%}

if标签语法如下:

{%if ...%}
逻辑1
{%elif ...%}
逻辑2
{%else%}
逻辑3
{%endif%}

关系比较操作符:

> < >= <= == !=
注意:进行比较操作是,比较操作符两边必须有空格。

逻辑比较:

not and or

  示例:  

{% for book in books %}
    {% if book.id < 3 %}
        <li class="red">{{ book.btitle }}</li>
    {% elif book.id == 3 %}
        <li class="gold">{{ book.btitle }}</li>
    {% elif book.id > 3 %}
        <li class="green">{{ book.btitle }}</li>
    {% endif %}
{% endfor %}
{% for book in books2 %}
{% empty %}
    <li>流星蝴蝶剑</li>
% endfor %}

过滤器 

  • 使用管道符号|来应用过滤器,用于进行计算、转换操作,可以使用在变量、标签中。
  • 如果过滤器需要参数,则使用冒号:传递参数。
  • 过滤器用于对模板变量进行操作

语法:

  • 变量|过滤器:参数

內建过滤器参数

  • date:改变日期的显示格式。
    • Y表示年,格式为4位,y表示两位的年。
    • m表示月,格式为01,02,12等。
    • j表示日,格式为1,2等。
    • H表  示时,24进  制,h表示12进制的时。
    • i表示分,为0-59。
    • s表示秒  ,为0-59。
  • 示例:
    • value|date:"Y年m月j日 H时i分s秒"

 

  • length:长度length,返回字符串包含字符的个数,列表、元组、字典的元素个数。
  • 默认值default,如果变量不存在时则返回默认值。
    • data|default:‘默认值‘

更多內建过滤器。http://python.usyiyi.cn/translate/django_182/ref/templates/builtins.html

 

示例:

{% for book in books %}
    {% if book.btitle|length < 5 %}
        <li>{{ book.btitle }}--{{ book.bpub_date|date:‘Y年-m月-j日‘ }}</li>
    {% else %}
        <li>{{ book.btitle }}--{{ book.bpub_date }}</li>
    {% endif %}
{% endfor %}
{# 使用不存在的模板变量时设置默认值 #}
	{{ date|default:"hello" }}

自定义过滤器流程

 

  1. 在应用的目录里创建templatetags包
  2. .在包当中定义filter.py文件

示例:

# coding=utf-8
# 引入注册对象
from django.template import Library
register=Library()
# 使用装饰器进行注册
@register.filter
# 定义求余函数mod,将value对2求余
def mod(num):
    return num%2 == 0
# 带参数的的过滤器
@register.filter
def mod(num, val):
    return num%val == 0

  3.在html文件中导入(和内置的过滤器用法相同)

{%load filters%}
{% if book.id|mod %}
    <li class="red">{{ book.btitle }}---{{ book.bpub_date|date:‘Y-m-j‘ }}</li>
{% else %}
    <li class="green">{{ book.btitle }}---{{ book.bpub_date|date:‘Y年-m月-j日‘ }}</li>
{% endif %}

带参数的用法

{% if book.id|mod:3 %}
	<li class="red">{{ book.btitle }}---{{ book.bpub_date|date:‘Y-m-j‘ }}</li>
{% else %}
    <li class="green">{{ book.btitle }}---{{ book.bpub_date|date:‘Y年-m月-j日‘ }}</li>
{% endif %}

注释

 

在模板中使用如下模板注释,这段代码不会被编译,不会输出到客户端;html注释只能注释html内容,不能注释模板语言。
单行注释:

{# 注释内容 #}

多行注释:

{% comment %}
注释内容
{% endcomment %}

模板继承

概述:

模板继承和类的继承含义是一样的,主要是为了提高代码重用,减轻开发人员的工作量。典型应用:网站的头部、尾部信息。

在父模板里可以定义块,使用标签:

{% block 块名 %}
块中间可以写内容,也可以不写
{% endblock 块名%}

子模板去继承父模板之后,可以重写父模板中的某一块的内容。
继承格式:

{% extends 父模板文件路径%}
{% block 块名 %}
{{ block.super}} #获取父模板中块的默认内容
重写的内容
{% endblock 块名%}

示例父模板

<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <title>base</title>
</head>
<body>
<h1>标题</h1>
{% block b1 %}
    <p>base的信息---b1</p>
{% endblock b1 %}
{% block b2 %}
    <p>base的信息---b2</p>
{% endblock b2 %}
<h1>导航</h1>
</body>
</html>

示例子模板

{% extends ‘booktest/base.html‘ %}
{% block b1 %}
    {{ block.super }}
   <h2>子模板--b1</h2>
{% endblock b1 %}
{% block b2 %}
    {{ block.super }}
    <h2>子模板--b2</h2>
{% endblock %}

总结:把不同的内容写在块里面,相同的的内容写在块的外面,相同的内容会被子模板继承

Ajax

 

在不全部加载某一个页面部的情况下,对页面进行局的刷新

HTML中ajax案例

GET方式:

 

{# username,password为用户提交的表单中的数据 #}
$.get(‘/login_ajax_check/?username=‘+username+"&password="+password, function (data) { if(data.res == ‘ok‘){
  {# data为视图传过来的参数 #} location.href = http://www.mamicode.com/‘/success/‘
    {# location.href让浏览器访问success页面 #} } lse{ $(‘#errinfo‘).html(‘用户名或密码错误‘).show() } })

 

POST方式: 

{# username,password为用户提交的表单中的数据 #}
$.post(‘/login_ajax_check/‘,{‘username‘:username, ‘password‘: password}, function (data) {
	alert(data.res)
})

  

CSRF

CSRF全拼为Cross Site Request Forgery,译为跨站请求伪造。CSRF指攻击者盗用了你的身份,以你的名义发送恶意请求。CSRF能够做的事情包括:以你名义发送邮件,发消息,盗取你的账号,甚至于购买商品,虚拟货币转账......造成的问题包括:个人隐私泄露以及财产安全。

跨站请求伪造产生原因
1个浏览器访问2个不同的网站A,B
2.浏览器登录A网站成功后会将登录的状态信息session保存到浏览器下一次访问的时候直接就显示登录成功的网页,不需要登录原因是浏览器会把保存的session状态信息带过去验证,通过后不必显示登录页面
3.现在用同一个浏览器访问B网站,紧接着将数据提交到A网站上,此时因为用的是同一个浏览器,会将之前产生的session数据一同提交到A网站上,此时还会把之前保存的session信息提交到A的网站上,同过验证,就产生了跨站请求伪造的情况

解决方法:

  • 重要信息如金额、积分等,采用POST方式传递
  • 启用CSRF中间件,默认启用《在项目的配置文件中设置》
  • ‘django.middleware.csrf.CsrfViewMiddleware‘, CSRF中间件配置--默认开启
  • 在form表单中加入标签csrf_token《{% csrf_token %}》

说明
当启用中间件并加入标签csrf_token后,会向客户端浏览器中写入一条Cookie信息,这条信息的值与隐藏域控制的value属性是一致的,提交到服务器后会先由csrf中间件进行验证,如果对比失败则返回403页面,而不会进行后续的处理

反向解析

问题产生:

随着功能的增加会出现更多的视图,可能之前配置的正则表达式不够准确,于是就要修改正同表达式,但是正则表达式一旦修改了,之前所有对应的超链接都要修改,真是一件麻烦的事情,而且可能还会漏掉一些超链接忘记修改,有办法让链接根据正则表达式动态生成吗? 

答:反向解析

说明:反向解析会根据应用当中的url匹配的改变,而改变对应html提交的url。。

使用流程:

不带参数的反向解析
1.在项目的url.py文件当中写入

url(r‘^‘, include(‘booktest.urls‘, namespace="booktest"))

2.在应用的url当中写入

url(r‘^fan6/$‘, views.fan1, name=‘fan2‘),

3.在对应的html文件当中写入:

<a href="http://www.mamicode.com/{% url ‘booktest:fan2‘ %}">反向解析</a> 

位置参数的反向解析
2.在应用的url当中写入

url(r‘^delete_(\d+)_(\d+)/$‘, views.reverse_url_need_args, name=‘delete‘), #带参数的反向解析

3.在对应的html文件当中写入:

<a href="http://www.mamicode.com/{% url ‘booktest:delete‘ 3 4 %}">带参数的反向解析</a><br>

关键字参数的反向解析
2.在应用的url当中写入

url(r‘^delete_(?P<p1>\d+)_(?P<p2>\d+)/$‘, views.reverse_url_need_args, name=‘delete2‘), #带关键字参数的反向解析

3.在对应的html文件当中写入:

<a href="http://www.mamicode.com/{% url ‘booktest:delete2‘ p1=33 p2=44 %}">关键字参数的反向解析</a>

重定向的时候使用反向解析

导入:from django.core.urlresolvers import reverse

不带参数

return redirect(reverse(‘booktest:fan2‘))

位置参数

return redirect(reverse(‘booktest:delete‘, args=(33, 44)))

关键字参数

return redirect(reverse(‘booktest:delete2‘, kwargs={‘p1‘: 22, ‘p2‘: 33}))

Django中模板总结[模板语言,模板继承,CSRF攻击,反向解析]