05-Django模板

一、模板概述

  • 模板组成

    HTML代码
    动态插入的代码(挖坑、填坑逻辑控制代码)
    
    
  • 作用

    快速生成HTML页面
    
    
  • 优点

    模板的设计实现了业务逻辑与现实内容的分离
    视图可以使用任何模板
    
    
  • 模板处理

    加载
    渲染
    
    

二、定义模板

  • 变量

    - 视图传递给模板的数据
    - 变量遵守标识符规则
    - 语法
      {{ var }}
    - 注意
      变量若不存在,则插入空的字符串
    - 点语法
     字典查询、属性或方法、数字索引 
    
    
  • 标签

    - 语法
      {% tag %}
    - 作用
      在输出中创建文本
      控制逻辑和循环
    
    
  • 单行注释

      {# 注释内容 #}
    
    
  • 标签if

    - 语法1
      {% if 条件 %}
          语句
      {% endif %}
    - 语法2
      {% if 条件 %}
          语句1
      {% else %}
          语句2
      {% endif %}
    - 语法3
      {% if 条件 %}
          语句1
      {% elif 条件 %}
          语句2
      {% elif 条件 %}
          语句3
      ....
      {% else %}
          语句
      {% endif %}
    - 例如
      {% if username %}
          欢迎  {{username}}  回来
      {%else%}
          游客登录,新用户注册有惊喜!
      {%endif%}
    
    
  • 标签for

    - 格式1
      {% for 变量 in 列表 %}
          语句
      {% endfor %}
    - 格式2
      {% for 变量 in 列表 %}
          语句1
      {% empty %}
          语句2
      {% endfor %}
      备注: 列表为空或列表不存在时执行语句2
    - 格式3
      {{forloop.counter}} 表示当前是第几次循环
    - 例如
      {% for student in students %}
          
  • 我叫{{student.sname}},性别{{student.ssex}},今年{{student.sage}}岁,座右铭:"{{student.sbrief}}"。
  • {% endfor %} - 例如
      {% for name in names %} {% if forloop.counter|divisibleby:2 %}
    • {{forloop.counter}} - {{name}}
    • {% else %}
    • {{forloop.counter}} - {{name}}
    • {% endif %} {% empty %}
    • 没有学生喔.
    • {% endfor %}
  • 标签comment

    - 作用
      多行注释
    - 例如
      {% comment %}
          

    姓名: {{student.sname}}

    性别: {{student.ssex}}

    年龄: {{student.sage}}

    座右铭: {{student.sbrief}}

    {% endcomment %}
  • 标签ifequal、ifnotequal

    - 作用
      判断值1与值2是成立
    - 例如
      {% ifequal 'hello' 'world' %}
          

    喔,hello和world一样呢。

    {% endifequal %} - 例如 # return render(request, 'meituan/testtemp.html',{'class1':'python03','class2':'python03'}) {% ifequal class1 class2 %}

    你们在同一个班级呢。

    {% else %}

    你们是不同班级。

    {% endifequal %}
  • 过滤器

    - 作用
      在变量被显示前修改它
    - 语法
      {{ var|过滤器 }}
    - lower 小写
      

    {{str|lower}}

    - upper 大写

    {{str|upper}}

    - join 传递参数(参数用引号引住)

    {{list|join:'#'}}

    - default 默认值(如果一个变量没有被提供或值为false、空,可以使用默认值)

    {{username|default:'游客'}}

    - date 根据给定格式转换日期为字符串

    {{dateValue|date:'y-m-d'}}

  • 标签inlcude

    - 作用
      加载模板并以标签内的参数渲染
    - 格式
      {% include '模板目录' 参数1 参数2 %}
    - 例如:
      # 不传递参数
      {% include "content.html" %}
      # 传递参数scoreList
      {% include "content.html" with scores=scoreList  %}
    
    

    由零合一,先完成小细节,最后使用include一起包含进去!

  • 标签url

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

    备注: 具体看下面详细说明。

  • 标签block、extends

    - 作用
      用于模板的继承
    
    

    备注: 具体看下面详细说明。

  • 标签autoescape

    - 作用
      用于HTML转义
    
    

    备注: 具体看下面详细说明。

  • 标签csrf_token

    - 作用
      用于跨域请求伪造保护
    - 格式
      {% csrf_token %}
    
    

    备注: 具体看下面详细说明。

三、反向解析

- 反向解析语法
  {% url 'namespace:name' p1 p2 %}

- 项目的urls.py文件中
  url(r'^meituan/', include('app.urls', namespace='app') )

- 应用的urls.py文件中
  # 路由(带参数)  
  url(r'^goods/(\d+)/$',views.goods, name='goods'),

  # 视图函数(带参数,和url与之对应)
  def goods(request, page):
    return HttpResponse('商品列表: 第%s页' % page)

- 模板(带有参数的)
   商品列表 
  {{ student.s_name }}

备注:
  name属性,即是给对对应的url添加一个名字;
  但是使用 name 也存在一定的问题 ,比如在同一个项目中的不同的app中 name 可能会重名;
  Django在反解URL时,会在项目全局顺序搜索,当查找到第一个name指定URL时,立即返回;
  当不小心定义相同的name时,可能会导致URL反解错误,为了避免这种事情发生,引入了命名空间;
  namespace命名空间;

反向解析场景: 正常情况下页面中设置的商品页链接地址都是goods/,而在服务器中路由如果发生一些细微的改变时,那么在页面中所有关于商品页链接地址都需要修改。为此可以使用反向解析解决此问题。

四、模板继承

  • 作用

    模板继承可以减少页面内容的重复定义,实现页面的复用。
    
    
  • block标签

    - 作用
      在父木模板中预留区域,子模板去填充
    - 语法
      {% block 标签名 %}
      {% endblock 标签名 %}  
    
    
  • extends标签

    - 作用
      继承模板,需要写在模板文件的第一行
    - 语法
      {% extends '父模板路径' %}
    
    
  • 示例(定义父模板)

    
    
    
      
      {% block title %}
      {% endblock title %}
      
      {% block style %}
      {% endblock style %}
    
    
    
      
      
    
      
      
    {% block content %} {% endblock content %}

    {% block test %} {% endblock test %}
  • 示例(定义子模板1)

    {% extends 'meituan/base.html' %}
    
    {% block content %}
      

    首页 --- 主体内容

    关于我们 {% endblock content %}
  • 示例(定义子模板2)

    {% extends 'meituan/base.html' %}
    
    {% block title %}
      关于我们
    {% endblock title %}
    
    {% block style %}
    
    {% endblock style %}
    
    {% block content %}
      

    about关于我们

    {% endblock content %} {% block test %}

    我住隔壁,我姓王,你有事情我帮忙。

    {% endblock test %}

五、HTML转义

  • 问题

    
    return render(request,'meituan/test2.html',{'code': '

    今天是周一.

    '}) {{code}} 将接受到的code当前普通字符串渲染
  • 转义

    将接受到字符串当成HTML代码渲染
    
    {{code|safe}}
    
    
    
    {% autoescape off %}
      {{code}}
    {% endautoescape %}
    
    

六、CSRF

- 跨域请求伪造
    某些恶意网站包含链接、表单、按钮、JS,利用用户登录在浏览器中认证,从而攻击服务
- 放置CSRF
    在settings.py文件中MIDDLEWARE添加'django.middleware.csrf.CsrfViewMiddleware'
    在form表单中添加 '{% csrf_token %}'
- 例如
{% csrf_token %}

在没有放置CSRF时,会报错一下错误Forbidden (403) CSRF verification failed. Request aborted. More information is available with DEBUG=True.

七、验证码

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

request.session.get["k1"],如果不存在则会报错,为了防止出错可以request.session.get('k1',none)

  • 示例(视图之生成验证码)
# 验证码
def verifycode(request):
    # 导入绘图模块
    from PIL import Image,ImageDraw,ImageFont
    # 导入随机函数模块
    import random
    # 文件操作
    import io

    # 定义变量,用于图片的背景色、宽、高
    # random.randrange()返回指定递增基数集合中的一个随机数
    bgcolor = (random.randrange(20,100),random.randrange(20,100),random.randrange(20,100))
    width = 100
    heigh = 50

    # 创建图片
    image = Image.new('RGB',(width,heigh),bgcolor)

    # 创建画笔对象
    draw = ImageDraw.Draw(image)

    # 调用画笔的point函数,绘制噪点
    for i in range(0,100):
        xy = (random.randrange(0,width),random.randrange(0,heigh))
        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(path) # 指定路径加载字体
    # font = ImageFont.load_default() # 加载一个默认的字体
    # truetype(font=None, size=10, index=0, encoding="", layout_engine=None)
    font = ImageFont.truetype('fonts/Songti.ttc',40)
    # font = ImageFont.truetype('fonts/STXINGKA.ttf',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个字
    # def text(self, xy, text, fill=None, font=None, anchor=None, *args, **kwargs):
    draw.text((5, 2), rand_str[0], font=font, fill=fontcolor1)
    draw.text((25, 2), rand_str[1], font=font, fill=fontcolor2)
    draw.text((50, 2), rand_str[2], font=font, fill=fontcolor3)
    draw.text((75, 2), rand_str[3], font=font, fill=fontcolor4)

    # 释放画笔
    del draw

    # 存入session,用于验证
    request.session['verify'] = rand_str

    # 文件操作
    buff = io.BytesIO()
    # 将图片保存在内存中,文件类型png
    image.save(buff,'png')

    # 将内存中图片数据返回给客户端,MIME类型为图片类型
    # 直接是返回验证码图片
    return HttpResponse(buff.getvalue(),'image/png')

PIL(Python Imaging Library)是Python一个强大方便的图像处理库,名气也比较大,不过只支持到Python 2.7。Pillow是PIL的一个派生分支,但如今已经发展成为比PIL本身更具活力的图像处理库。目前最新版本是3.0.0。
ython 3.x 安装Pillow: pip install Pillow

  • 示例(视图之登录)
# 登录操作
def verifycodefile(request):
    # 获取到session的flag标志值
    flag = request.session.get("flag", True)
    str = ''
    if flag == False:
        str = "请重新输入"

    # 清空session
    request.session.clear()

    return render(request, 'meituan/verifycodefile.html', {"flag": str})

  • 示例(视图之登录验证码验证)
# 登录验证
def verifycodecheck(request):
    # 输入的验证码
    # upper()转为大写
    code1 = request.POST.get('verifycode').upper()
    # session验证码
    code2 = request.session['verify'].upper()

    if code1 == code2:  # 验证成功
        return render(request,'meituan/success.html')
    else:   # 重新登录操作
        request.session["flag"] = False
        return redirect('/meituan/verifycodefile/')

  • 示例(url管理器)
urlpatterns=[
    url(r'^verifycode/$',views.verifycode), # 验证码测试
    url(r'^verifycodecheck/$',views.verifycodecheck),    # 验证操作
    url(r'^verifycodefile/$',views.verifycodefile),  # 带验证码登录
]

  • 示例(模板)



    
    登录 | 验证码测试


    
    

    
    
{%csrf_token%}

{{flag}}

你可能感兴趣的:(05-Django模板)