Django模板进阶(第十二天)

一、模板的功能

产生html,控制页面上展示的内容。模板文件不仅仅是一个html文件。
模板文件包含两部分内容:
1)静态内容:css,js,html;
2)动态内容:用于动态去产生一些网页内容。通过模板语言来产生。

二、模板文件的使用

通常是在视图函数中使用模板产生html内容返回给客户端。
a)加载模板文件 loader.get_template
获取模板文件的内容,产生一个模板对象
b)定义模板上下文 RequeseContext
给模板文件传递数据。
c)模板渲染产生html页面内容render
用传递的数据替换相应的变量,产生一个替换后的表中html内容。

from django.shortcuts import render
from django.template import loader, RequestContext
from django.http import HttpResponse
# Create your views here.

def my_render(request, template_path, context={}):
    # 1.加载模板文件,获取一个模板对象
    temp = loader.get_template(template_path)
    # 2.定义模板上下文,给模板文件传数据
    context = RequestContext(request, context)
    context.push(locals())
    # 3.模板渲染,产生一个替换后的html内容
    res_html = temp.render(context=locals(), request=request)
    # 4.返回应答
    return HttpResponse(res_html)

# /index
def index(request):
    # return my_render(request, 'xm20200504/index.html')
    return render(request, 'xm20200504/index.html')

三、模板文件加载顺序

在这里插入图片描述
1)首先去配置的模板目录下面去找模板文件
2)去settings.py里面INSTALLED_APPS下面的每个应用去找模板文件,前提是应用中必须有templates文件夹

四、模板语言

1、模板变量
模板变量名是由数字,字母,下划线和点组成的,不能以下划线开头。
使用模板变量:{{模板变量名}}
模板变量的解析顺序:
例如:{{ book.btitle}}
1)book当成一个字典,btitle当成键名,进行取值book[‘btitle’]
2)book当成一个对象,btitle当成属性,进行取值book.btitle
3)book当成一个对象,btitle当成方法,进行取值book.btitle
例如:{{book.0}}
1)book当成一个字典,把0当成键名,进行取值book[‘0’]
2)book当成一个列表,把0当成下标,进行取值book[0]
如果解析失败,则产生内容时用空字符串填充模板变量

2、模板标签
{% 代码段 %}
for循环:
{% for x in 列表 %}
#列表不为空时执行
{% empty %}
#列表为空时执行
{% endfor %}
可以通过{{ forloop.counter }}得到for循环遍历到了第几次。
{% if条件 %}
{% elif条件 %}
{% else %}
{% endif %}

3、过滤器
过滤器用于对模板变量进行操作。
date:改变日期的显示格式
length:求长度。字符串,列表,元组,字典长度
default:设置模板变量的默认值
格式:模板变量 | 过滤器:参数
参考资料:https://blog.csdn.net/lengfengyuyu/article/details/83342639
自定义过滤器
自定义的过滤器函数,至少有一个参数,最多两个。
操作:在应用下新建python包,固定命名为templatetags,在该包下面创建python文件,自定义命名,编辑内容例如:

# 自定义过滤器
# 过滤器其实就是python函数
from django.template import Library

# 创建一个Library类的对象
register = Library()
 
# 自定义的过滤器函数,至少有一个参数,最多两个
@register.filter
def mod(num):
    '''判断num是否为偶数'''
    return num%2 == 0
 

@register.filter
def mod_val(num, val):
    '''判断num是否能被整除'''
    return num%val == 0

在前端页面需要将自定义过滤器的文件加载过来,在模板html中的head标签上添加命令

{% load 自定义过滤器python文件的命名名称 %}

另外,在html中编辑如下代码进行数据过滤

{% if book.id|mod %}
{% if book.id|mod_val:2 %}

4、模板注释
单行注释: {# 注释内容 #}
多行注释: {% comment %}
                   注释内容
                    {% endcomment %}

五、模板继承

子模板要继承父模板的所有内容,重用html页面内容,新建个html文件,使用extends关键字编辑代码即可。

{% extends '父模板html文件路径(包含html文件名称)' %}
{% extends 'booktest/base.html' %}

通常情况下,子模板继承父模板的内容作为自身部分内容,还有一些其他内容要通过子模板页面显示出来,就需要在父模板上面编写预留块,这个预留块就可以在子模板上重写,父模板格式如下:

{% block b1 %}
	<h1>这是父模板b1块中的内容</h1>
{% endblock b1 %}

子模板格式如下:

{% block b1 %}
	{{ block.super }}    # 这句可以继承父模板预留块中内容过来
	<h1>这是子模板b1块中的内容</h1>
{% endblock b1 %}

这样当访问子模板页面时就会将父模板的预留块替换掉显示出来。

六、html转义

在模板上下文中的html标记默认是会被转义的。比如

小于号< 转换为&lt;
大于号> 转换为&gt;
单引号' 转换为&#39;
双引号" 转换为&quot;
与符号& 转换为&amp;

要关闭模板上下文字符串的转义,可以使用{{ 模板变量|safe }}
也可以使用:
{% autoescape off %}
    模板语言代码
{% endautoescape off %}
模板硬编码中的字符串默认不会经过转义,如果需要转义,需要手动进行转义,如:

{{ test|default:'<h1>hello</h1>' }}
手动进行转义:
{{ test|default:'&lt;h1&gt;hello&lt;/h1&gt;' }}

七、登录装饰器

在用户处于未登录状态时,用户访问login之外的其他页面时会自动跳转到登录页面,做成这种效果就需要在视图views中创建登录装饰器函数,另外在需要通过登录后才能访问的函数之前添加@装饰器函数名称。

from django.shortcuts import render, redirect
def login_required(view_func):
    '''登录判断装饰器'''
    def wrapper(request, *view_args, **view_kwargs):
        # 判断用户是否登录
        if request.session.has_key('islogin'):
            # 用户已登录,调用对应的视图
            return view_func(request, *view_args, **view_kwargs)
        else:
            # 用户未登录,跳转到登录页
            return redirect('/login')
    return wrapper
    
@login_required
def change_pwd(request):
    '''显示修改密码页面'''
    return render(request, 'xm20200504/change_pwd.html')

八、csrf(跨站请求)攻击

1、csrf伪造与防护
当我们注释掉settings.py中第47行的’django.middleware.csrf.CsrfViewMiddleware’时容易发生csrf伪造。我们在访问自己网站修改密码时候没有及时退出账号,再继续通过访问其他第三方网站页面时,如果点击到了其他按钮或图片,可能会通过表单提交到我们网站进行密码伪造。
当我们取消注释’django.middleware.csrf.CsrfViewMiddleware’时则会出现自己网站表单提交跳转时报403错误,只针对post提交,可以在我们的表单页面加上{% csrf_token %}进行解决

<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <title>登陆页面</title>
</head>
<body>
<form method="post" action="/login_check">
    {% csrf_token %}
    用户名:<input type="text" name="username" value="{{ username }}"><br/>
    密码:<input type="password" name="password"><br/>
    <input type="checkbox" name="remember">记住用户名<br/>
    <input type="submit" value="登陆">
</form>
</body>
</html>

防护原理:
1)渲染模板文件时在页面生成一个名字叫做csrfmiddlewaretoken的隐藏域;
2)服务器交给浏览器保存一个名字为csrftoken的cookie信息;
3)提交表单时,两个值都会发给服务器,服务器进行比对,如果一样,则csrf验证通过,否则失败。

九、验证码

在用户注册、登录页面,为了防止暴力请求,可以加入验证码功能,如果验证码错误,则不需要继续处理,可以减轻业务服务器、数据库服务器的压力。

#引入绘图模块
from PIL import Image, ImageDraw, ImageFont
#引入随机函数模块
import random
# /verify_code
def verify_code(request):
    #定义变量,用于画面的背景色、宽、高
    bgcolor = (random.randrange(20, 100), random.randrange(20, 100), random.randrange(20, 100))
    width = 100
    height = 50
    #创建画面对象
    im = Image.new('RGB', (width, height), bgcolor)
    #创建画笔对象
    draw = ImageDraw.Draw(im)
    #调用画笔的point()函数绘制噪点
    for i in range(0, 100):
        xy = (random.randrange(0, width), random.randrange(0, height))
        fill = (random.randrange(0, 255), 255, random.randrange(0, 255))
        draw.point(xy, fill=fill)
    #定义验证码的备选值
    str = '1234567890QWERTYUIOPASDFGHJKLZXCVBNMqwertyuiopasdfghjklzxcvbnm'
    #随机选取4个值作为验证码
    rand_str = ''
    for i in range(0, 4):
        rand_str += str[random.randrange(0, len(str))]
    #构造字体对象
    # font = ImageFont.truetype('楷体', 40)
    #构造字体颜色
    fontcolor1 = (255, random.randrange(0, 255), random.randrange(0, 255))
    fontcolor2 = (255, random.randrange(0, 255), random.randrange(0, 255))
    fontcolor3 = (255, random.randrange(0, 255), random.randrange(0, 255))
    fontcolor4 = (255, random.randrange(0, 255), random.randrange(0, 255))
    #绘制4个字
    draw.text((5, 2), rand_str[0], fill=fontcolor1)
    draw.text((25, 2), rand_str[1], fill=fontcolor2)
    draw.text((50, 2), rand_str[2], fill=fontcolor3)
    draw.text((75, 2), rand_str[3], fill=fontcolor4)
    #释放画笔
    del draw
    # 存入session,用于做进一步验证
    request.session['verifycode'] = rand_str
    #内存文件操作
    import io
    buf = io.BytesIO()
    #将图片保存在内存中,文件类型为png
    im.save(buf, 'png')
    #将内存中的图片数据返回给客户端,MIME类型为图片png
    return HttpResponse(buf.getvalue(), 'image/png')

十、url反向解析

当某一个url配置的地址发生变化时,页面上使用反向解析生成地址的位置不需要发生变化。
根据url正则表达式的配置动态的生成url。
在项目urls中包含具体应用的urls文件时指定namespace

urlpatterns = [
    path('admin/', admin.site.urls),
    url(r'^', include('yy20200504.urls', namespace='yy20200504')),
]

在应用的urls中配置指定name

urlpatterns = [
    url(r'^index/$', views.index, name='index'),
    url(r'^index2/$', views.index2, name='index2'),
]

在模板文件中使用时,格式如下:

{% url 'namespace名字:name' %}
带位置参数:
{% url 'namespace名字:name' 参数值 %}
带关键字参数:
{% url 'namespace名字:name' 关键字参数=参数值 %}

在视图views.py重定向的时候使用反向解析:

from django.core.urlresolvers import reverse
无参数:
reverse('namespace名字:name名字')
如果有位置参数:
reverse('namespace名字:name名字', args = 位置参数元组)
如果有关键字参数:
reverse('namespace名字:name名字', kwargs = 字典)
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值