自学Python之路-django模板--模板语法
django模板中包括两部分:
- 变量。
- 内置标签。
变量会在模板渲染时被其值代替,内置标签负责逻辑控制。
1 变量
变量在模板中的表示为:{{ 变量名 }},变量名就是render中context中的键。
变量可以基本类型中的数值、字符串、布尔,也可以是字典、对象、列表等。
django提供了点号来访问复杂数据结构。
- 列表、元组的元素可以使用索引引用,不能使用负索引,语法:变量.索引
- 字典: 字典变量.key
- 对象: 对象.属性 对象.方法名(方法不能有参数)
当模板系统在变量名中遇到点时,按照以下顺序尝试进行查找:
- 字典类型查找
- 属性查找
- 方法调用
- 列表类型索引
如果模板中引用变量未传值,则会被置为空,不会报错,除非你对其进行了操作。
#App2\urls.py urlpatterns = [ path("var/", views.handle_var, name='var'), ] #App2\views.py def handle_var(request): num = 10 name = "伟大的意大利左后卫" students = [10,20,30,40,50] student = {'name':'马尔蒂尼','age':30} return render(request,"变量.html",locals())
2 过滤器
- 过滤器相比模板标签要简单的多,我们可以把它们理解成一个 Python 函数,传递参数给他处理就可以了,当滤器接收参数后对它进行处理,最终将处理结果返回到模板中,这就是整个过滤器的实现流程。
- 过滤器是在变量显示之前修改它的值的一个方法,过滤器使用管道符。
过滤器可以串联调用:
{{ 变量|方法 }}
过滤器 | 描述 | 示例 |
upper | 以大写方式输出 | {{ user.name | upper }} |
add | 给value加上一个数值 | {{ user.age | add:”5” }} |
addslashes | 单引号加上转义号 | |
capfirst | 第一个字母大写 | {{ ‘good’| capfirst }} 返回”Good” |
center | 输出指定长度的字符串,把变量居中 | {{ “abcd”| center:”50” }} |
cut | 删除指定字符串 | {{ “You are not a Englishman” | cut:”not” }} |
date | 格式化日期 | |
default | 如果值不存在,则使用默认值代替 | {{ value | default:”(N/A)” }} |
default_if_none | 如果值为None, 则使用默认值代替 | |
dictsort | 按某字段排序,变量必须是一个dictionary | {% for moment in moments | dictsort:”id” %} |
dictsortreversed | 按某字段倒序排序,变量必须是dictionary | |
divisibleby | 判断是否可以被数字整除 |
{{ 224 | divisibleby:2 }} 返回 True |
escape | 按HTML转义,比如将”<”转换为”<” | |
filesizeformat | 增加数字的可读性,转换结果为13KB,89MB,3Bytes等 |
{{ 1024 | filesizeformat }} 返回 1.0KB |
first | 返回列表的第1个元素,变量必须是一个列表 | |
floatformat | 转换为指定精度的小数,默认保留1位小数 | {{ 3.1415926 | floatformat:3 }} 返回 3.142 四舍五入 |
get_digit | 从个位数开始截取指定位置的数字 | {{ 123456 | get_digit:’1’}} |
join | 用指定分隔符连接列表 | {{ [‘abc’,’45’] | join:’*’ }} 返回 abc*45 |
length | 返回列表中元素的个数或字符串长度 | |
length_is | 检查列表,字符串长度是否符合指定的值 | {{ ‘hello’| length_is:’3’ }} |
linebreaks | 用<p>或<br>标签包裹变量 | {{ “Hi\n\nDavid”|linebreaks }} 返回<p>Hi</p><p>David</p> |
linebreaksbr | 用<br/>标签代替换行符 | |
linenumbers | 为变量中的每一行加上行号 | |
ljust | 输出指定长度的字符串,变量左对齐 | {{‘ab’|ljust:5}}返回 ‘ab ’ |
lower | 字符串变小写 | |
make_list | 将字符串转换为列表 | |
pluralize | 根据数字确定是否输出英文复数符号 | |
random | 返回列表的随机一项 | |
removetags | 删除字符串中指定的HTML标记 | {{value | removetags: “h1 h2”}} |
rjust | 输出指定长度的字符串,变量右对齐 | |
slice | 切片操作, 返回列表 | {{[3,9,1] | slice:’:2’}} 返回 [3,9]{{ 'asdikfjhihgie' | slice:':5' }} 返回 ‘asdik’ |
slugify | 在字符串中留下减号和下划线,其它符号删除,空格用减号替换 |
{{ '5-2=3and5 2=3' | slugify }} 返回 5-23and5-23 |
stringformat | 字符串格式化,语法同python | |
time | 返回日期的时间部分 | |
timesince | 以“到现在为止过了多长时间”显示时间变量 | 结果可能为 45days, 3 hours |
timeuntil | 以“从现在开始到时间变量”还有多长时间显示时间变量 | |
title | 每个单词首字母大写 | |
truncatewords | 将字符串转换为省略表达方式 |
{{ 'This is a pen' | truncatewords:2 }}返回 This is ... |
truncatewords_html | 同上,但保留其中的HTML标签 |
{{ '<p>This is a pen</p>' | truncatewords:2 }}返回 <p>This is ...</p> |
urlencode | 将字符串中的特殊字符转换为url兼容表达方式 | {{ ‘http://www.aaa.com/foo?a=b&b=c’ | urlencode}} |
urlize | 将变量字符串中的url由纯文本变为链接 | |
wordcount | 返回变量字符串中的单词数 | |
yesno | 将布尔变量转换为字符串yes, no 或maybe |
{{ True | yesno }} |
简单的例子add给value加上一个值:
# App02\views.py def handle_filter(request): num = 20 name = "hello carlos" return render(request,"过滤器.html",locals()) # App02\urls.py urlpatterns = [ path("filter/", views.handle_filter, name='filter'), ]
简单的例子default_if_none如果值为None,使用默认值替换:
# App02\views.py def handle_filter(request): num = 20 name = "hello carlos" age = None return render(request,"过滤器.html",locals())
简单的例子date 格式化日期:
# App02\views.py from datetime import datetime def handle_filter(request): t1 = datetime.now() return render(request,"过滤器.html",locals()) # App02\urls.py urlpatterns = [ path("filter/", views.handle_filter, name='filter'), ]
自定义过滤器:
Django 在提供诸多可供选择的过滤器的同时,也向开发者提供了自定义过滤器功能,当内置过滤器无法满足开发者的需求的时候,就可以使用自定义过滤器,实现起来也非常的方便。
定义过滤器函数时需要遵循以下规则:
- 函数名必须以“filter_”为前缀;
- 函数的第一个参数必须是要处理的变量;
- 函数可以有任意数量的参数,但是不能超过两个;
- 函数必须返回处理后的值。
第一步:在app中创建一个包:templatetags
第二步:在包里创建一个py文件
# App02\templatetags\mytag.py
from django import template # 实例化自定义过滤器注册对象 register = template.Library() # name代表在模板中使用的过滤器的名称 @register.filter(name='hello') def hello(value,arg): """ :param value: 传给hello过滤的值 :param arg: hello自带的参数 :return: """ return value + str(arg) @register.filter('time_ago') def time_ago(value): """ 定义一个距离当前时间多久之前的过滤器 :param value: :return: 1.如果时间间隔小于1分钟内,那么就显示刚刚 2.如果时间间隔大于1分钟小于1小时,那么就显示xx分钟前 3.如果时间间隔大于1小时小于24小时,那么就显示xx小时前 4.如果时间间隔大于24小时小于30天,那么就显示xx天前 5.如果时间间隔大于30天,那么就显示具体时间 """ if not isinstance(value, datetime.datetime): return value now = datetime.datetime.now() timestamp = (now - value).total_seconds() if timestamp < 60: return '刚刚' elif timestamp >= 60 and timestamp < 60 * 60: return '{}分钟前'.format(int(timestamp / 60)) elif timestamp >= 60 * 60 and timestamp < 60 * 60 * 24: return '{}小时前'.format(timestamp / 60 / 60) elif timestamp >= 60 * 60 * 24 and timestamp < 60 * 60 * 23 *30: return '{}天前'.format(int(timestamp / 60 / 60 / 24)) else: return value.strftime('%Y-%m-%d %H:%M')
第三步:在模板中使用
{% load hello %} #加载自定义过滤器的模块 <!DOCTYPE html> <html lang="en"> <head> <meta charset="UTF-8"> <title>Title</title> </head> <body> {{ name |hello:' how are you' }} #使用自定义过滤器 </body> </html>
3 内置标签
语法:{% tag %}
3.1 if 标签
{% if express1 %} # to do {% elif express2 %} # to do {% else %} # to do {% endif %}
① if 表达式中使用以下运算符(优先级从高到低):
- < >= <= == !=
- in 、not in
- is、is not
- not
- and
- or
②不要在 if 表达式中使用(),构造复杂条件智能使用 if 嵌套实现功能。
③不支持 if 3 < b < 5这种写法
简单的例子如下:
# App02\views.py def handle_tag(request): l1 = [10,20,30,40,50] num = 21 return render(request,"tag.html",locals()) # App02\urls.py urlpatterns = [ path("tag/", views.handle_tag, name='tag'), ]
3.2 for标签
遍历可迭代对象
{% for x in y %} ... {% endfor %}
反向迭代(reversed):
{% for value in c [1,2,3,4,5] reversed %} <span>{{ value }}---</span> {% endfor %}
empty 当可迭代对象为空或不存在时执行,否则不执行:
{% for value in c %} <span>{{ value }}---</span> {% empty %} 数据不存在 {% endfor %}
字典迭代:
# e = {'a1':20,'b1':40} {% for k,v in e.items %} <div>{{ k }}---{{ v }}</div> {% endfor %}
获取 for 循环迭代的状态:
变量名称 | 变量说明 |
forloop.counter | 获取迭代的索引 从1开始 |
forloop.counter0 | 获取迭代的索引 从0开始 |
forloop.revcounter | 迭代的索引从最大递减到1 |
forloop.revcounter0 | 迭代的索引从最小递减到0 |
forloop.first | 是否为第⼀次迭代 |
forloop.last | 是否为最后⼀次迭代 |
forloop.parentloop | 获取上层的迭代对象 |
{% for i in c %} <li>{{ forloop.first }}</li> <li>{{ forloop.last }}</li> <li>{{ forloop.counter }}</li> <li>{{ forloop.counter0 }}</li> <li>{{ forloop.revcounter }}</li> <li>{{ forloop.revcounter0 }}</li> {% endfor %}
简单的例子如下:
# App02\views.py def handle_tag(request): l1 = [200,201,202,203,204] num = 21 return render(request,"tag.html",locals()) # App02\urls.py urlpatterns = [ path("tag/", views.handle_tag, name='tag'), ]
如果为空,返回“数据不存在”
# App02\views.py def handle_tag(request): # 注释掉l1 = [200,201,202,203,204] num = 21 return render(request,"tag.html",locals())
# 反向遍历 {% for value in l1 reversed %} <li>{{ value }} </li> {% empty %} 数据不存在 {% endfor %}
3.3 ifequal/ifnotequal标签
于判断两个值相等或不等的。
{% ifequal var var %} {% endifequal %} {% ifnotequal var var %} {% endifnotequal %}
3.4 注释
{# 注释的内容 #}
多行注释
{% comment %}
...
{% endcomment %}
3.5 跨站请求伪造 csrf
防止网站站受第三方服务器的恶意攻击(确定表单到底是不是本网站的表单传递过来的)。
csrf相当于在表达中增加了一个隐藏的input框,用于向服务器提交一个唯一的随机字符串用于服务器验证表单是否是本服务器的表单。
使用:
# settings.py MIDDLEWARE = [ 'django.middleware.csrf.CsrfViewMiddleware', ] # 表单里 <form action="" method="post"> {% csrf_token %} <input type="text" name="username"> <p><input type="submit"></p> </form>
全站禁用csrf :
# 在settings中设置 MIDDLEWARE = [ 'django.middleware.security.SecurityMiddleware', 'django.contrib.sessions.middleware.SessionMiddleware', 'django.middleware.common.CommonMiddleware', #'django.middleware.csrf.CsrfViewMiddleware', 'django.contrib.auth.middleware.AuthenticationMiddleware', 'django.contrib.messages.middleware.MessageMiddleware', 'django.middleware.clickjacking.XFrameOptionsMiddleware', ]
局部禁用csrf:
#在不想检验csrf的视图函数前添加装饰器@csrf_exempt。 from django.views.decorators.csrf import csrf_exempt,csrf_protect
@csrf_exempt def csrf1(request): pass
ajax验证csrf :
Ajax提交数据时候,携带CSRF: a. 放置在data中携带 <form method="POST" action="/csrf1.html"> {% csrf_token %} <input id="username" type="text" name="username" /> <input type="submit" value="提交"/> <a onclick="submitForm();">Ajax提交</a> </form> <script src="/static/jquery-1.12.4.js"></script> <script> function submitForm(){ var csrf = $('input[name="csrfmiddlewaretoken"]').val(); var user = $('#user').val(); $.ajax({ url: '/csrf1.html', type: 'POST', data: { "user":user,'csrfmiddlewaretoken': csrf}, success:function(arg){
console.log(arg); } }) } </script>
注意:
csrf的意义在于给每一个表单都设置一个唯一的csrf的值,
并且cookie也存储一份当提交表单过来的时候 判断cookie中的值 和csrf_token中的值 是否都为本网站生成的,
如果验证通过则提交,否则 403 。
......
作者:CARLOS_CHIANG
出处:http://www.cnblogs.com/yaoyaojcy/
本文版权归作者和博客园共有,欢迎转载,但未经作者同意必须保留此段声明,且在文章页面明显位置给出原文链接。
posted on 2023-03-14 07:23 CARLOS_KONG 阅读(437) 评论(0) 编辑 收藏 举报