Django - 04-Django模板

[toc]

1

2 定义模板

2.1 变量

视图传递给模板的数据;

传递的变量要遵守标识符规则;

语法:
        {{ 变量 }}
        num = {{ num }}

注意:
        如果使用的变量不存在,则插入的是空字符串;

在模板中使用点语法(对象.属性):
        字典查询
        属性或方法
        数字索引
        
在模板中调用对象的方法:
        注意:  不能传递参数

2.2 标签

语法:
        {% tag %}


作用:
        1. 在输出中创建文本
        2. 控制逻辑和循环
        
if
        格式:
                {% if 表达式1 %}
                    语句
                {% endif %}
            # --------------------------
                {% if 表达式1 %}
                    语句
                {% else %}
                    语句
                {% endif %}
            # --------------------------
                {% if 表达式1 %}
                    语句
                {% elif 表达式2 %}
                    语句
                ......
                {% else %}
                    语句
                {% endif %}
                
        栗子:
                test.html
                        <body>
                            {% if num %}
                            <h1>Python is Best;{{ num }}</h1>
                            {% endif %}
                        </body>
                        
                views.py
                        def templateTest(request):
                            num = 10
                            return render(request, 'myapp/test.html', {'num':num})
                            
                urls.py
                        url(r'^templateTest', views.templateTest),

for
        格式:
                {% for 变量 in 列表 %}
                    语句
                {% endfor %}
                # ----------------------------------------------------------
                {% for 变量 in 列表 %}
                    语句1
                {% empty %}
                    语句2
                {% endfor %}
                        注意: 列表为空或者不存在时,执行语句2
                # ----------------------------------------------------------      
                {{ forloop.counter }}   在for内使用,表示当前第几次循环;
                
        栗子:
                test.html
                        <body>
                            <ul>
                                {% for stu in stulist %}
                                    <li>{{ forloop.counter }} | {{ stu.sname }} | {{ stu.sgrade }}</li>
                                {% empty %}
                                    <h1>这里没有学生</h1>
                                {% endfor %}
                            </ul>
                        </body>
                        
                views.py
                        def templateTest2(request):
                            stulist = Student.stuObj2.all()
                            return render(request, 'myapp/test.html', {'stulist':stulist})
                            
                urls.py
                        url(r'^templateTest2/$', views.templateTest2),

comment
        作用:
                多行注释
                
        格式:
                {% comment %}
                    注释的内容
                {% endcomment %}

ifequal/ifnotequal
        作用:
                判断相等/判断不相等
                
        格式:
                {% ifequal 值1 值2 %}
                    语句
                {% endifequal %}
                
                当 值1 == 值2,则执行 语句;否则不执行语句;

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

url
        作用:
                反向解析
                
        格式:
                {% url'namespace:name' 参数1 参数2 %}

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

block/extends
        作用:
                用于模板继承

autoescape
        作用:
                用于html转义


2.3 过滤器

        作用:
                在变量被显示前修改它
                
        语法:
                {{ 变量 | 过滤器 }}
        
        栗子:
                test.html
                        <body>
                            {{ python|upper }}
                        </body>
                        
                views.py
                        def templateTest(request):
                            num = 10
                            return render(request, 'myapp/test.html', {'num': num, 'python': 'python is best.'})
                            
        过滤器:
                upper
                        {{ python|upper }}
                lower
                过滤器可以传递参数,参数用引号引起来;
                        join
                                格式: {{ 列表|join:'#' }}
                                栗子:
                                        test.html
                                                {{ list|join:'#' }}
                                        
                                        views.py
                                                templateTest(request):
                                                return render(request, 'myapp/test.html', {'list': ['Abc', 'qqq', 'qwer']})
                                                
                        default
                                作用:如果一个变量没有被提供,或者值为Flase、空,可以使用默认值 
                                格式: {{ 变量|default:'good' }}
                                
                        date
                                作用: 根据给定格式转换日期为字符串
                                格式: {{ date变量|date:'y-m-d'}}
                                
                        escape
                                作用: HTML转义
                                
                        safe
                                作用: HTML转义
                                格式: {{ 变量|safe }}                                
                                         
                        加减乘除
                                加:num = {{ num|add:10 }}
                                减:num = {{ num|add:-10 }}
                                乘:{% widthratio num 1 5 %}  # num/1*5
                                除:{% widthratio num 2 1 %}  # num/2*1
                                
                        divisibleby
                                num|divisibleby:2
                                        num/2 能除尽,则返回 True;

2.4 注释

单行注释
        <# 注释的内容 #>
多行注释
        <% connment %>
        <% endcomment %>

2.5 反向解析

通过定义在 urls.py 文件中的 namespace 和 name 参数,在模板中拼接出href参数,避免由于urls.py中的正则修改而大量的修改模板参数;

使用方法:
        自动拼接出 127.0.0.1:8000/good/1/:
        
        project/urls.py
                url(r'^', include('myApp.urls', namespace='myApp')),
        
        myApp/urls.py
                url(r'^good/(\d+)/$', views.good, name='good'),
                
        views.py
                def good(request, num):
                    return render(request, 'myApp/good.html', {'num': num})
                        
        index.html
                <h1><a href="/good/123">链接123</a></h1><br>
                <h1><a href="{% url 'myApp:good' 1 %}">链接</a></h1>
                
        good.html
                <h1>good--{{ num }}</h1>

2.6 模板继承

作用:
        模板继承,可以减少页面内容的重复定义,实现页面的重用;
        
block标签:
        在父模板中预留区域;
        在子模板去填充父模板的预留区域;
        语法:
                {% block 标签名 %}
                    ......
                {% endblock 标签名 %}


extends标签
        继承模板,需要卸载模板文件的第一行;
        语法:
                {% extends 父模板路径 %}
        
栗子:
        定义父模板:
                base.html
                    <div id="header">header</div>
                    <div id="main">
                        {% block main%}
                
                        {% endblock %}
                    </div>
                    <div id="footer">footer</div>
                
        定义子模板:
                main.html
                    {% extends 'myApp/base.html' %}
                    {% block main %}
                        <h1>lance is a good man</h1>
                    {% endblock %}
                    
        urls.py
                url(r'^main/$', views.main),
                
        views.py
                def main(request):
                    return render(request, 'myApp/main.html')

2.7 html转义

问题:
        在 views.py 中传递 html 代码,在模板中,会将接受到的代码当字符串渲染;
                good.html
                    {{ code }}
                
                views.py
                    def good(request):
                        return render(request, 'myApp/good.html', {'code':'<h1>lance is a good man</h1>'})

解决:
        方法一:safe过滤器
            {{ code|safe }}
            
        方法二:autoescap标签
            {%  autoescape off %}       # 设置为on,则会当成字符串处理;
            {{ code }}{{ code }}
            {% endautoescape %}
        

2.8 CSRF

跨站请求伪造
        某些恶意网站包含链接、表单、按钮、DNS,会利用登录用户在浏览器中的认证,攻击服务;
        
防止CSRF
        在 settings.py 的 MIDDLEWARE 增加 'django.middleware.csrf.CsrfViewMiddleware';
        
        在表单中加入 csrf_token 标签,防止自己的表单被拦截;
                <form action="/showinfo/" method="post">
                {% csrf_token %}
                姓名:<input type="text" name="username">
                <hr>
                密码:<input type="password" name="password">
                <hr>
                <input type="submit" value="登录">
</form>

2.9 验证码

作用:
        在用户注、登录页面时候,防止暴力请求,减轻服务器压力;
        防止csrf的一种方式;
        
栗子:
        views.py
                # 绘制验证码
                def verifycode(request):
                    # 引入绘图模块
                    from PIL import Image, ImageDraw, ImageFont
                    # 引入随机函数模块
                    import random
                    # 引入字符串模块
                    import string
                
                    # 设置画面背景色,从20到100中随机生成RGB颜色代码
                    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 = string.digits + string.ascii_letters
                    # 选取4个值作为验证码
                    rand_str = ''
                    for i in range(0,4):
                        rand_str += str[random.randrange(0, len(str))]
                    # 构造字典体对象
                    font = ImageFont.truetype(r'./arial.ttf', 40)
                
                    # 构造字体颜色
                    fontcolor = (255, random.randrange(0, 255), random.randrange(0, 255))
                    # 绘制4个字体
                    draw.text((5, 2), rand_str[0], font=font, fill=fontcolor)
                    draw.text((25, 2), rand_str[1], font=font, fill=fontcolor)
                    draw.text((50, 2), rand_str[2], font=font, fill=fontcolor)
                    draw.text((75, 2), rand_str[3], font=font, fill=fontcolor)
                    # 释放画笔
                    del draw
                    # 存入session,用于做进一步验证
                    request.session['verify'] = rand_str
                    # 内存文件操作
                    import io
                    buf = io.BytesIO()
                    # 将图片文件保存在内存中,文件类型png
                    im.save(buf, 'png')
                    return HttpResponse(buf.getvalue(), 'image/png')
                
                # 登录页面
                def verifycodefile(request):
                    return render(request, 'myApp/verifycodefile.html')
                
                # 登录验证
                from django.shortcuts import redirect
                def verifycodecheck(request):
                    code1 = request.POST.get('verifycode').upper()
                    code2 = request.session.get('verify').upper()
                    print(code1)
                    print(code2)
                    if code1 == code2:
                        return  render(request, 'myApp/success.html')
                    else:   # 登录失败返回登录页面
                        return  redirect('/verifycodefile/')
                        
        #-----------------------------------------------------------------------------------
        urls.py
                # 验证码图片的url
                url(r'^verifycode/$', views.verifycode),
                # 登录界面url
                url(r'^verifycodefile/$', views.verifycodefile),
                # 登录验证
                url(r'^verifycodecheck/$', views.verifycodecheck),
                
        #-----------------------------------------------------------------------------------
        verifycodefile.html
                <form action="/verifycodecheck/" method="post">
                    {% csrf_token %}
                    姓名:<input type="text" name="username">
                    <hr>
                    密码:<input type="password" name="password">
                    <hr>
                    验证码:<input type="text" name="verifycode">
                    <img src="/verifycode/" alt="">
                    <input type="submit" value="登录">
                </form>
©著作权归作者所有,转载或内容合作请联系作者
  • 序言:七十年代末,一起剥皮案震惊了整个滨河市,随后出现的几起案子,更是在滨河造成了极大的恐慌,老刑警刘岩,带你破解...
    沈念sama阅读 217,657评论 6 505
  • 序言:滨河连续发生了三起死亡事件,死亡现场离奇诡异,居然都是意外死亡,警方通过查阅死者的电脑和手机,发现死者居然都...
    沈念sama阅读 92,889评论 3 394
  • 文/潘晓璐 我一进店门,熙熙楼的掌柜王于贵愁眉苦脸地迎上来,“玉大人,你说我怎么就摊上这事。” “怎么了?”我有些...
    开封第一讲书人阅读 164,057评论 0 354
  • 文/不坏的土叔 我叫张陵,是天一观的道长。 经常有香客问我,道长,这世上最难降的妖魔是什么? 我笑而不...
    开封第一讲书人阅读 58,509评论 1 293
  • 正文 为了忘掉前任,我火速办了婚礼,结果婚礼上,老公的妹妹穿的比我还像新娘。我一直安慰自己,他们只是感情好,可当我...
    茶点故事阅读 67,562评论 6 392
  • 文/花漫 我一把揭开白布。 她就那样静静地躺着,像睡着了一般。 火红的嫁衣衬着肌肤如雪。 梳的纹丝不乱的头发上,一...
    开封第一讲书人阅读 51,443评论 1 302
  • 那天,我揣着相机与录音,去河边找鬼。 笑死,一个胖子当着我的面吹牛,可吹牛的内容都是我干的。 我是一名探鬼主播,决...
    沈念sama阅读 40,251评论 3 418
  • 文/苍兰香墨 我猛地睁开眼,长吁一口气:“原来是场噩梦啊……” “哼!你这毒妇竟也来了?” 一声冷哼从身侧响起,我...
    开封第一讲书人阅读 39,129评论 0 276
  • 序言:老挝万荣一对情侣失踪,失踪者是张志新(化名)和其女友刘颖,没想到半个月后,有当地人在树林里发现了一具尸体,经...
    沈念sama阅读 45,561评论 1 314
  • 正文 独居荒郊野岭守林人离奇死亡,尸身上长有42处带血的脓包…… 初始之章·张勋 以下内容为张勋视角 年9月15日...
    茶点故事阅读 37,779评论 3 335
  • 正文 我和宋清朗相恋三年,在试婚纱的时候发现自己被绿了。 大学时的朋友给我发了我未婚夫和他白月光在一起吃饭的照片。...
    茶点故事阅读 39,902评论 1 348
  • 序言:一个原本活蹦乱跳的男人离奇死亡,死状恐怖,灵堂内的尸体忽然破棺而出,到底是诈尸还是另有隐情,我是刑警宁泽,带...
    沈念sama阅读 35,621评论 5 345
  • 正文 年R本政府宣布,位于F岛的核电站,受9级特大地震影响,放射性物质发生泄漏。R本人自食恶果不足惜,却给世界环境...
    茶点故事阅读 41,220评论 3 328
  • 文/蒙蒙 一、第九天 我趴在偏房一处隐蔽的房顶上张望。 院中可真热闹,春花似锦、人声如沸。这庄子的主人今日做“春日...
    开封第一讲书人阅读 31,838评论 0 22
  • 文/苍兰香墨 我抬头看了看天上的太阳。三九已至,却和暖如春,着一层夹袄步出监牢的瞬间,已是汗流浃背。 一阵脚步声响...
    开封第一讲书人阅读 32,971评论 1 269
  • 我被黑心中介骗来泰国打工, 没想到刚下飞机就差点儿被人妖公主榨干…… 1. 我叫王不留,地道东北人。 一个月前我还...
    沈念sama阅读 48,025评论 2 370
  • 正文 我出身青楼,却偏偏与公主长得像,于是被迫代替她去往敌国和亲。 传闻我的和亲对象是个残疾皇子,可洞房花烛夜当晚...
    茶点故事阅读 44,843评论 2 354