xss攻击

XSS攻击全称跨站脚本攻击,是为不和层叠样式表(Cascading Style Sheets, CSS)的缩写混淆,故将跨站脚本攻击缩写为XSS,XSS是一种在web应用中的计算机安全漏洞,
它允许恶意web用户将代码植入到提供给其它用户使用的页面中。

为了防止xss攻击djano是这样做的?

auto_escape (自动转义):何谓转义?就是把html语言的关键字过滤掉。例如,<div>就是html的关键字,如果要在html页面上呈现<div>,其源代码就必须是&lt;div&gt; 

Django的模板中会对HTML标签和JS等语法标签进行自动转义,原因显而易见,这样是为了安全。

但是有的时候我们可能不希望这些HTML元素被转义,比如我们做一个内容管理系统,后台添加的文章中是经过修饰的,这些修饰可能是通过一个类似于FCKeditor编辑加注了HTML修饰符的文本,如果自动转义的话显示的就是保护HTML标签的源文件。

为了在Django中关闭HTML的自动转义有两种方式,如果是一个单独的变量我们可以通过过滤器“|safe”的方式告诉Django这段代码是安全的不必转义。

比如:后端传过来的是:

value = "<a href='#'>点我</a>"

我们可以在前端页面上这样设置:

{{ value|safe}}

常用语法

只需要记两种特殊符号:

{{  }}和 {% %}

变量相关的用{{}},逻辑相关的用{%%}。

变量

{{ 变量名 }}

变量名由字母数字和下划线组成。

点(.)在模板语言中有特殊的含义,用来获取对象的相应属性值。

几个例子:

view中代码:

复制代码
def template_test(request):
    l = [11, 22, 33]
    d = {"name": "alex"}

    class Person(object):
        def __init__(self, name, age):
            self.name = name
            self.age = age

        def dream(self):
            return "{} is dream...".format(self.name)

    Alex = Person(name="Alex", age=34)
    Egon = Person(name="Egon", age=9000)
    Eva_J = Person(name="Eva_J", age=18)

    person_list = [Alex, Egon, Eva_J]
    return render(request, "template_test.html", {"l": l, "d": d, "person_list": person_list})
复制代码

模板中支持的写法:

复制代码
{# 取l中的第一个参数 #}
{{ l.0 }}
{# 取字典中key的值 #}
{{ d.name }}
{# 取对象的name属性 #}
{{ person_list.0.name }}
{# .操作只能调用不带参数的方法 #}
{{ person_list.0.dream }}
复制代码

Filters

语法: {{ value|filter_name:参数 }}

default

{{ value:default: "nothing"}}

如果value值没传的话就显示nothing

length

{{ value|length }}

'|'左右没有空格没有空格没有空格

返回value的长度,如 value=['a', 'b', 'c', 'd']的话,就显示4.

filesizeformat

将值格式化为一个 “人类可读的” 文件尺寸 (例如 '13 KB''4.1 MB''102 bytes', 等等)。例如:

{{ value|filesizeformat }}

如果 value 是 123456789,输出将会是 117.7 MB。

slice

切片

{{value|slice:"2:-1"}}

date

格式化'

html 代码:

{{ value|date:"Y-m-d H:i:s"}}

views.py 代码

import datetime
now=datetime.datetime.now()

truncatechars

如果字符串字符多于指定的字符数量,那么会被截断。截断的字符串将以可翻译的省略号序列(“...”)结尾。

参数:截断的字符数

{{ value|truncatechars:9}}

自定义filter

自定义filter代码文件摆放位置:

复制代码
app01/
    __init__.py
    models.py
    templatetags/  #注意这个文件名字一定要一样不可改变,这个是一个python包
        __init__.py
        app01_extras.py
    views.py
复制代码

编写自定义filter

复制代码
from django import template  #先导入
register = template.Library()  # 再注册,注意Library后面有括号


@register.filter(name="cut")  #name 只是个别名
def cut(value, arg):
    return value.replace(arg, "")


@register.filter(name="addSB")
def add_sb(value):
    return "{} SB".format(value)
复制代码

使用自定义filter

{ somevariable|cut:"0" }}
{{ {{ d.name|addSB }} }}

在前面页面的代码:

{% load app_01tap %} {#先在HTML中导入你写的那个函数#}
{{ s1|s8:"我们" }}  #s1是我们要输入的内容 s8是我们定义的函数名,'我们'是函数中要传入的参数arg

模板标签

标签看起来像是这样的: {% tag %}。标签比变量更加复杂:一些在输出中创建文本,一些通过循环或逻辑来控制流程,一些加载其后的变量将使用到的额外信息到模版中。

一些标签需要开始和结束标签 (例如{% tag %} ...标签 内容 ... {% endtag %})。

for

<ul>
{% for user in user_list %}
    <li>{{ user.name }}</li>
{% endfor %}
</ul>

for循环可用的一些参数:

 

VariableDescription
forloop.counter 当前循环的索引值(从1开始)
forloop.counter0 当前循环的索引值(从0开始)
forloop.revcounter 当前循环的倒序索引值(从1开始)
forloop.revcounter0 当前循环的倒序索引值(从0开始)
forloop.first 当前循环是不是第一次循环(布尔值)
forloop.last 当前循环是不是最后一次循环(布尔值)
forloop.parentloop 本层循环的外层循环

for ... empty

复制代码
<ul>
{% for user in user_list %}
    <li>{{ user.name }}</li>
{% empty %}
    <li>空空如也</li>
{% endfor %}
</ul>
复制代码

if,elif和else

复制代码
{% if user_list %}
  用户人数:{{ user_list|length }}
{% elif black_list %}
  黑名单数:{{ black_list|length }}
{% else %}
  没有用户
{% endif %}
复制代码

当然也可以只有if和else

{% if user_list|length > 5 %}
  七座豪华SUV
{% else %}
    黄包车
{% endif %}

if语句支持 and 、or、==、>、<、!=、<=、>=、in、not in、is、is not判断。

with

定义一个中间变量

{% with total=business.employees.count %}
    {{ total }} employee{{ total|pluralize }}
{% endwith %}

csrf_token

这个标签用于跨站请求伪造保护。

在页面的form表单里面写上{% csrf_token %}

 

注释

{# ... #}

母板

复制代码
<!DOCTYPE html>
<html lang="en">
<head>
  <meta charset="UTF-8">
  <meta http-equiv="x-ua-compatible" content="IE=edge">
  <meta name="viewport" content="width=device-width, initial-scale=1">
  <title>Title</title>
  {% block page-css %} #替换css的快
  
  {% endblock %}
</head>
<body>

<h1>这是母板的标题</h1>

{% block page-main(自己起的块的名字) %}
这是需要替换的地方 {% endblock %} </body> </html>
复制代码

注意:我们通常会在母板中定义页面专用的CSS块和JS块,方便子页面替换。

继承母板

子页面要用模板是,首先在子页面中在页面最上方使用下面的语法来继承母板。

{% extends 'layouts.html' %}

块(block)

通过在母板中使用{% block  xxx %}来定义"块"。

然后在子页面中通过定义母板中的block,然后在块内写入子页面的内容。注意block块的名字要和母版中的块的名字相同,

{% block page-main %}
  <p>世情薄</p>
  <p>人情恶</p>
  <p>雨送黄昏花易落</p>
{% endblock %}

组件

可以将常用的页面内容如导航条,页尾信息等组件保存在单独的文件中,然后在需要使用的地方按如下语法导入即可。弊端: 谁用这个组件谁的后端还需要传参数

{% include 'navbar.html' %}

静态文件相关

{% load static %}
<img src="{% static "images/hi.jpg" %}" alt="Hi!" />

引用JS文件时使用:

{% load static %}
<script src="{% static "mytest.js" %}"></script>

某个文件多处被用到可以存为一个变量

{% load static %}
{% static "images/hi.jpg" as myphoto %}
<img src="{{ myphoto }}"></img>

使用get_static_prefix

{% load static %}
<img src="{% get_static_prefix %}images/hi.jpg" alt="Hi!" />

或者

{% load static %}
{% get_static_prefix as STATIC_PREFIX %}

<img src="{{ STATIC_PREFIX }}images/hi.jpg" alt="Hi!" />
<img src="{{ STATIC_PREFIX }}images/hi2.jpg" alt="Hello!" />

 自定义simpletag

和自定义filter类似,只不过接收更灵活的参数。

定义注册simple tag

@register.simple_tag(name="plus")
def plus(a, b, c):
    return "{} + {} + {}".format(a, b, c)

使用自定义simple tag

{% load app01_demo %}

{# simple tag #}
{% plus "1" "2" "abc" %}

 创建自定义模板标签

背景原因

Django有许多内置的模板标签(template tags)比如{% if %} ,{% for cate in cate_list %}.... 如果这些模板标签不能满足您的需要,你也可以自己定义模板标签.

 

Django提供了以下帮助函数(functions)来允许你以一种简单的方式创建自己的模板标签(template tags):

  • simple_tag:处理数据并返回一个字符串(string) , 从前端取数据,然后在后端处理成变量,替换前端. 例子:计算器
  • inclusion_tag:处理数据并返回一个渲染过的模板(template),后端处理数据渲染前端页面
  • assignment_tag:处理数据并在上下文(context)中设置一个变量(variable),这个我还没遇到过:

 

模板中自定义函数
  - 在注册的app中创建一个名字叫 templatetags 的包,这个文件夹的名字必须叫它. 这个app,一定在setting.py 中的installapps中已经注册,也就是存在
  - 在其下任意创建一个py文件, 比如叫text1.py文件的命名是非常重要的。你将在模板(template)中使用这些模块的名字加载你的标签(tags)。
  - 创实例化一个名字叫register 的Library类的对象
  - 定义函数

      - 在使用自定义simple_tag和filter的html文件中导入之前在templatetags中创建的py文件

#第一种方法: register.filter 过滤器   

HTML中的参数传入到函数中当做该函数的参数,然后该函数返回数据给前端渲染页面.

第一个例子:

 

from django import template
register = template.Library()
@register.filter
def f(a):
    print(a)
    return "你好"

html页面:设置为:

{% load text1 %} #先导入这个文件
{{ "建超"| f }}

后端打印结果为:

建超

前端页面渲染为:

你好

 第二个例子:  在前端页面中f2可以先传入个参数,最后会一起传到后端来.,注意后端的f2()中也要有两个参数

from django.template import Library
register=Library()
@register.filter #必须要加上装饰器
def f2(a1,a2):  #这种方法这里只能传两个参数,但是可以放在if判断中
    data= "我的名字叫%s,我喜欢%s"%(a1,a2)
    return data

HTML:

{% load text1 %} #先导入这个文件
{{ "建超"|f2:"小红" }}  第二个参数是函数后边紧跟着冒号然后跟参数

页面:

 

#第二种方法 @ register.simple_tag   #这个可以传传多个参数装饰器和上面的不一样了, 但是这种方法不能放在if判断中

@register.simple_tag   #这个是传多个参数装饰器和上面的不一样了, 但是这种方法不能放在if判断中
def f3(a1,a2,a3,a4):
    data=a1+a2+a3+a4
    return data

 HTML

{% load text1 %} #先导入这个文件
{% f3 4 45 46 47 %}  #这里的调用方式和

 

前端:


register.filter 用在if 判断 中
 py
@register.filter
def f4(a1):
    if "alex" in a1:
        return "哈哈哈" #我发现,其实你在这里返回什么都无所谓
    else:
        return False

html

{% if "adljallex"|f4 %}
    <p>"回答正确"</p>
    {% else %}
    <p>"回答错误"</p>

{% endif %}

页面:

 第三个例子:blog博客系统左侧页面

  • inclusion_tag("需要渲染的html文件"):处理数据并返回一个渲染过的模板(template),后端处理数据渲染前端页面.  这个函数主要用在给母版传递数据

 templatetags 下的my_tag.py文件


from django import template
register=template.Library()
@register.inclusion_tag("base_tag.html") #括号里的HTML文件并不是母版中的HTML,而是需要传递数据的HTML页面
def get_archive_style(request):
menus_list = request.session["menus_list"]
menu_dict = {}
for i in menus_list:
if not i["parent_id"]:
i["active"] = False
menu_dict[i["permissions_id"]] = i
# 处理menus_list中的active值
import re
current_path = request.path_info
for i in menus_list:
url = "^%s$" % (i["url"])
if re.match(url, current_path):
if i["parent_id"]:
menu_dict["permissions_id"]["active"] = True
else:
i["active"] = True
menu_dict1 = {} #最后要的总值
for i in menu_dict.values():
if i["menus_id"] in menu_dict1.keys():
temp = {"title": i["permissions__title"], "url": i["url"], "active": i["active"]}
menu_dict1[i["menus_id"]]["children"].append(temp)
if i["active"]:
menu_dict1[i["menus_id"]]["active"] = True
else:
menu_dict1[i["menus_id"]] = {
"menu_name": i["menus__caption"],
"active": i["active"],
"children": [
{
"title": i["permissions__title"],
"url": i["url"],
"active": i["active"]
}
]
}
return {"menu_dict1":menu_dict1}
 
base_tag.html. 母版中的哪部分html代码需要传数据,把这部分代码剪切出来单独写一个html文件叫base_tag.html
{% for item in  menu_dict1.values %}
<p class="menu1"><a href="/m1/">{{ item.menu_name }}</a></p>
{% if item.active %}
<div class="list">
{% else %}
<div class="list hide">
{% endif %}
{% for son in item.children %}
{% if son.active %}
<p><a href="{{ son.url }}" class="active">{{ son.title }}</a></p>
{% else %}
<p><a href="{{ son.url }}" class=" ">{{ son.title }}</a></p>
{% endif %}
{% endfor %}
</div>
{% endfor %}
</div>

 base.html

{% load base_tag %} //导入templatetags文件夹中的py文件
<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <meta http-equiv="X-UA-Compatible" content="IE=edge">  <!--IE浏览器最高渲染-->
    <meta name="viewport" content="width=device-width, initial-scale=1"> <!--为了确保适当的绘制和缩放-->
    <title>Title</title>
{#        <link rel="stylesheet" href="https://cdn.bootcss.com/bootstrap/3.3.7/css/bootstrap.min.css">#}
    <style>
        * {
            margin: 0;

        }

        .header {
            width: 100%;
            height: 80px;
            background-color: coral;
        }

        .menu {
            width: 200px;
            height: 660px;
            background-color: darkgrey;
            color: white;
            float: left;
        }

        .hide {
            display: none;
        }

        .list {
            margin-left: 20px;
            margin-top: 10px;
        }

        .active {
            color: green;
        }

        a {
            text-decoration: none;
        }
    </style>
</head>
<body>
<div class="header">
    <h3>管理页面</h3>
</div>
<div class="content">
    <div class="row">
        <div class="menu col-md-3">
              {% get_archive_style request %} //导入py文件中的方法,并且传参数
        </div>
        <div class="col-md-8">
            {% block content_right %}

            {% endblock %}
        </div>

    </div>

</body>
</html>

 

 

 
posted on 2018-01-18 21:32  程序员一学徒  阅读(625)  评论(0)    收藏  举报