首页 > 技术文章 > Django_03_模板的使用

jiangzongyou 2019-11-14 14:38 原文

{{  }} 变量
list类型用 'lst.索引',且不支持倒序索引,即不能识别lst.-1
dic类型用 'dic.key',去取对应的value,不支持{}
对于实例对象,通常自己重写__str__,让返回的内容好看些
可以使用方法,例如'dic.keys',但不能使用()来启动方法,且被调用的方法也不能接收参数
注:当模板系统遇到 '.' 时,存在优先级
1.在字典中查询
2.属性或方法
3.数字索引
eg,若view函数中存在dic = {'keys':'xxx','name':12},
当在html中使用dic.keys时,取到的是xxx,而不是dict_keys(['keys', 'name'])
过滤器filter,作用:改变显示结果,语法{{变量名|filter_name:参数}}
-注意冒号:前后无空格,有空格就报错
-{{eqwe|default:参数}},eqwe在views中并没有定义或者是空,参数可以是int,string,或者是其它变量
-filesize=1025,{{ filesize|filesizeformat }} >>> 1.0 KB
-add,可以做算术运算(优先级>)字符串拼接(add:前后必须都是str类型),列表拼接(前后必须都是lst类型)
-lower小写,{{ value|lower }}
-upper大写,{{ value|upper}}
-length,{{ value|length }}返回value的长度,如 value=['a', 'b', 'c', 'd']的话,就显示4.
-slice切片,{{value|slice:"-2:0:-1"}}返'] 与切片的使用方法一样
-first取第一个,{{value|first }}
-last取最后一个,{{value|last }}
-join分割,{{lst|join:'|']
-truncatechars截断,{{ 'longstr'|truncatechars:5 }} >>> lo... ,最后三个.也要算在长度里面,只认英文,不认中文
-date,格式化时间,'time':datetime.datetime.now(),{{ time|date:'Y-m-d H:i:s' }},2019-11-10 14:29:58,记得是i和s,不是M和S
-date的另一种设置,在settings里面修改下面两种配置:
USE_L10N = False
DATETIME_FORMAT = 'Y-m-d H:i:s'
这样之后,只要django检查到参数time是时间格式的,就会自动把其格式转换成'Y-m-d H:i:s'
{{ time }} >>> 2019-11-10 14:34:57
-safe,告诉django不需要转义,比如:value = "<a href='#'>点我</a>",{{ value|safe }}
自定义filter
1.在app文件夹内创建一个名为'templatetags'的python包
-文件夹也可以,但官方文档说最好用包
-用了包之后,pycharm就可以加载这个包,在输入的时候,就可以智能补全,使用文件夹就没法智能提醒和补全
2.在这个包内新建一个my_tags.py文件,文件名可以任意
3.在这个文件中写入以下内容,register不能是其它名字,函数名可以任取
from django import template
register = template.Library()
@register.filter(name='haha') # haha就是add_xx函数的别名,使用的时候,要使用haha()
def add_xx(value,arg): # 最少一个参数(value),最多两个参数
return '{}-{}'.format(value,arg)
4.在html文件中
{% load my_tags %}
{{ 'wey'|add_xx:'sweet' }}
>>> wey-sweet

day7 {% %} 标签
forloop
forloop.counter 当前循环的索引值(从1开始)
forloop.counter0 当前循环的索引值(从0开始)
forloop.revcounter 当前循环的倒序索引值(到1结束)
forloop.revcounter0 当前循环的倒序索引值(到0结束)
forloop.first 当前循环是不是第一次循环(布尔值)
forloop.last 当前循环是不是最后一次循环(布尔值)
forloop.parentloop 本层循环的外层循环
{# 需求:对行列均处于偶数位置的数据进行标红#} 要会使用forloop.parentloop
<table border="1">
<tbody>
{% for hobby in hobbies %}
<tr>
{% for hobby_in in hobby %}
{% if forloop.counter|divisibleby:2 and forloop.parentloop.counter|divisibleby:2 %}
<td style="color: red">{{ hobby_in }}</td>
{% else %}
<td>{{ hobby_in }}</td>
{% endif %}
{% endfor %}
</tr>
{% endfor %}
</tbody>
</table>
for...empty 去看图书馆里项目的/book_list/
<ul>
{% for user in user_list %}
<li>{{ user.name }}</li>
{% empty %}
<li>空空如也</li>
{% endfor %}
</ul>
if...elif...else..endif, elif和else都不是必须项
注意: if语句支持 and 、or、==、>、<、!=、<=、>=、in、not in、is、is not判断。
{% if user_list %}
用户人数:{{ user_list|length }}
{% elif black_list %}
黑名单数:{{ black_list|length }}
{% else %}
没有用户
{% endif %}
连续判断
python中 10>5>1, 10>5 and 5>1,True and True,True
模板中和js中,10>5>1,True>1,Flase,即不支持连续判断,而且也不支持 if 2 + 2 == 4,因为不识别+-*/
with 中间变量 改名字 仅仅在with里面才生效
{% with hobby=hobbies.2.2 %} # 等号前后不能有空格
{{ hobby }}
{% endwith %}
注释
{# ... #} 这是django的注释语法,里面的内容不会翻译,也不会放在最终的html文档中
<!-- {{ string }} --> 这时html的注释,里面的变量会被翻译,会被放在html文档中,但不会显示出来
csrf_token
csrf: 跨站请求伪造
form表单里面写上{% csrf_token %},就可以防止跨站伪造,且不用再在settings里面注释csrf了
原理: django在html里加了一个隐藏的input标签,其value是是给服务器做验证用的
<input type="hidden" name="csrfmiddlewaretoken" value="nwSD71CUEPor07CRbX7L2tkGZFGAPDOSWZSf1qANLlkngeMrn5EfBorazxYQsxKf">
母版和继承
母版:一个普通的html,其拥有了多个页面的公共部分,不同的地方用{% block 名字 %}{% endblock %}标记
继承:
首先引入母版{% extends 'base.html' %},注意引号(如果不加引号,那就是变量,需在render里传入相应的参数),且必须放在首行
然后在需要的地方使用{% block 名字 %}xxx{% endblock %}来修改母版中的内容,要修改的内容xxx必须写在block块中,否则不显示
在head最后加上{% block cs %}{% endblock %},给需要继承的页面留出空间,好加载其自己的css样式
在body最后加上{% block js %}{% endblock %},给需要继承的页面留出空间,好加载其自己的js样式
组件
插入一小段html代码,例如,把图书管理系统的导航栏单独拿出来
{% include 'navbar.html' %}
静态文件,load static 可以动态的去检索settings里面的STATIC_URL = '/static/',然后做拼接
{% load static %}
{% get_static_prefix %} {# /static/#}
<link rel="stylesheet" href="{% static '/plugins/bootstrap-3.3.7/css/bootstrap.css' %}">
<link rel="stylesheet" href="{% static '/css/dashboard.css' %}">

自定义filter补充
-@register.simple_tag的使用,比@register.filter好用一些,因为可以传入任意数量的参数
在my_tags文件里设置
@register.simple_tag
def push(value,*args,**kwargs):
return '{}-{}-{}'.format(value,'#'.join(args),'$'.join(kwargs.values()))
在html使用的时候,设置
{% load my_tags %}
{% push lst '1' '2' k1='3' k2='4' k3='5' %}
# lst是render传过来的变量,类型是list,可以在这里使用,说明simple_tag对参数类型不限制
-@register.inclusion_tag('组件html全称'),可以传入任意数量的参数
在my_tags文件里设置
@register.inclusion_tag('组件html全称')
def page(num):
return {'num' : range(1,num+1)}
在html使用的时候,设置
{% load my_tags %}
{% page 2}
调用流程就是,2传给page函数,page函数return给组件html,
组件html通过{{num}}渲染完之后再交还到调用page的那个位置

推荐阅读