模板语法之过滤器、标签、自定义过滤器、标签、inclusion_tag、模板的导入、继承、模型层-查询方法all()与filter()、orm常见关键字操作
模板语法之过滤器(类似于内置函数)
语法结构
'{{ 数据对象|过滤器名称:参数 }} 过滤器最多只能额外传输一个参数'
常见过滤器
(django模板语法提供了60+过滤器 我们了解几个即可)
<p>统计数据的长度:{{ s1|length }}</p>
<p>算数加法或者字符串加法(拼接):{{ n1|add:100 }}、{{ s1|add:'hello baby' }}</p>
<p>将数字转成合适的文件计量单位:{{ file_size|filesizeformat }}、{{ file_size1|filesizeformat}}</p>
<p>判断当前数据对象对应的布尔值是否是False>>>:{{ s1|default:'前面的值对应的布尔值是False' }}、{{ f|default:'前面的值对应的布尔值是False' }}</p>
{#这个方法如果是true则直接返回对应的字符串,是false则返回default后面的值#}
<p>时间格式化:{{ c_time|date:'Y-m-d' }}</p>
<p>索引切片:{{ s1|slice:'0:3' }}</p>
<p>按照空格截取指定个数的文本{{ s2|truncatewords:4 }}</p>
<p>按照字符截取指定个数的文本(包含三个点):{{ s2|truncatechars:4 }}、{{ s1|truncatechars:6 }}</p>
<p>移除指定的字符:{{ s3|cut:'|' }}</p>
<p>是否取消转换:{{ tag1 }} {{ tag1|safe }}</p>
{#需要把后端的标签语法进行渲染需要加上safe告诉程序这个代码是安全的不必转义,也可以通过后端来实现#}
<p>通过后端实现转换:{{ res }}</p>
Django的模板中会对HTML标签和JS等语法标签进行自动转义,原因
显而易见,这样是为了安全。但是有的时候我们可能不希望这些
HTML元素被转义,比如我们做一个内容管理系统,后台添加的文章
中是经过修饰的,这些修饰可能是通过一个类似于FCKeditor编辑加
注了HTML修饰符的文本,如果自动转义的话显示的就是保护HTML标
签的源文件。为了在Django中关闭HTML的自动转义有两种方式,如
果是一个单独的变量我们可以通过过滤器“|safe”的方式告诉Django
这段代码是安全的不必转义。
ps:最后一个|safe启发了我们以后用django开发全栈项目前端页面代码(主要指HTML代码)也可以在后端编写
# views代码
def index(request):
s1 = '这是一串字符串'
n1 = 666
file_size = 10240
file_size1 = 10240000
t = True
f = False
c_time = datetime.today()
s2 = '1 2 3 4 5 7 8 9 0'
s3 = '1|2|3|4|5'
tag1 = '<h1>我是一级标签</h1>'
# 后端来实现safe转换
from django.utils.safestring import mark_safe
ttt = '<a href="https://www.baidu.com">百度啊</a>'
l1 = [11, 22, 33, 44, 55]
res = mark_safe(ttt)
user = {'name': 'tuzi', 'pwd': 123, 'hobby': 'ctrl'}
return render(request, 'index.html', locals())
结果:
模板语法之标签
"""
在django模板语法中写标签的时候 只需要写关键字然后tab键就会自动补全
"""
注释语法
<!----> 是HTML的注释语法
{# #} 是django模板语法的注释
"""
HTML的注释可以在前端浏览器页面上直接查看到
模板语法的注释只能在后端查看 前端浏览器查看不了
"""
语法结构
{% 名字 ...%}
{% end名字 %}
if判断
{% if 条件1 %}
条件成立后执行的代码
{% elif 条件2 %}
条件成立后执行的代码
{% else %}
条件成立后执行的代码
{% endif %}
for循环
提供了forloop关键字
{'parentloop': {}, 'counter0': 0, 'counter': 1, 'revcounter': 4, 'revcounter0': 3, 'first': True, 'last': False}
{'parentloop': {}, 'counter0': 0, 'counter': 1, 'revcounter': 4, 'revcounter0': 3, 'first': True, 'last': False}
{#first与last用来表示是否是第一次或者最后一次循环#}
{% 代码段 %}
#for循环:
#遍历列表:
{% for i in 列表 %}
#列表不为空时执行
{% empty %}
#列表为空时执行
{% endfor %}
#若加上关键字reversed则倒序遍历:
{% for x in 列表 reversed %}
{% endfor %}
#在for循环中可以通过{{ forloop.counter }}得到for循环遍历到几次
{#
for+if其他使用
{% for i in l1 %}
{% if forloop.first %}
<p>这是第一次循环</p>
{% elif forloop.last %}
<p>这是最后一次循环</p>
{% else %}
<p>中间循环</p>
{% endif %}
{% empty %}
<p>for循环对象为空 自动执行</p>
{% endfor %}
#}
针对字典同样提供了keys、values、items方法
{% for foo in user %}
{{ foo }}
{% endfor %}
{% for foo in user.keys %}
{{ foo }}
{% endfor %}
{% for foo in user.values %}
{{ foo }}
{% endfor %}
{% for foo in user.items %}
{{ foo }}
{% endfor %}
自定义过滤器、标签、inclusion_tag
"""
1.在应用下需要创建一个名为templatetags的文件夹
2.在该文件夹内创建一个任意名称的py文件
3.在该py文件内需要先提前编写两行固定的代码
from django import template
register = template.Library()
"""
上述操作完毕之后应该重启一下项目,否则Django无法读取到新建的 templatetags项目包
自定义过滤器:只能接收两个参数
'templatetags文件夹下的mytag文件'
from django import template # 导入模块
register = template.Library() # 标准语句都不能改,一字不差
@register.filter(is_safe=True) # 写函数装饰器
def index(a, b): # 最多有两个
return a + b # 返回两个值之和
'HTML文件'
{% load mytag %} # 引用模块
{{ n1|index:666 }} # 通过函数名使用
自定义简单标签:可以接收任意的参数
'templatetags文件夹下的mytag文件'
@register.simple_tag(name='my_tag')
def func1(a, b, c, d):
return a + b + c + d
'HTML文件'
{% my_tag 1 2 3 4 %} # 参数之间空格隔开即可
自定义inclusion_tag
'templatetags文件夹下的mytag文件'
@register.inclusion_tag('left.html')
def func2(n):
l1 = []
for i in range(1, n + 1):
l1.append(f'第{i}页')
return locals()
{% func2 10 %}
'left.html'
<ul>
{% for foo in l1 %}
<li>{{ foo }}</li>
{% endfor %}
</ul>
'''该方法需要先作用于一个局部html页面 之后将渲染的结果放到调用的位置'''
模板的导入(了解)
类似于将html页面上的局部页面做成模块的形式 哪个地方想要直接导入即可展示
eg:有一个非常好看的获取用户数据的页面 需要在网站的多个页面上使用
策略1:拷贝多份即可
策略2:模板的导入
使用方式
{% include 'menu.html' %}
模板的继承
{#1.先在模板中通过block划定将来可以被修改的区域#}
{% block content %}
<h1>主页内容</h1>
{% endblock %}
{# 2.子板继承模板 #}
{% extends 'home.html'%}
{# 3.对引入的模板块进行从写 #}
{% block demo %}
{# 4.子页面也支持使用父页面的功能 #}
{{ block.super }}
"""
模板上最少应该有三个区域
css区域、内容区域、js区域
子页面就可以有自己独立的css、js、内容
"""
eg:
在引入css的地方开设一个可以被修改的区域
{% block css %}
{% endblock %}
在引入js的地方开设一个可以被修改的区域
{% block js %}
{% endblock %}
模型层
前期数据准备
"""
django 自带的sqlite3数据库功能很少,并且针对日期类型不准确
1.数据库正向迁移命令(将类操作映射到表中)
python3 manage.py makemigrations
python3 manage.py migrate
2.数据库反向迁移命令(将表映射成类)
python3 manage.py inspectdb
"""
搭建测试环境
我们只想操作orm 不想使用网络请求
需要有专门的测试环境
1.自己搭建
import os
if __name__ == "__main__":
os.environ.setdefault("DJANGO_SETTINGS_MODULE", "Pythonexerciseday54_lianxi.settings")
import django
django.setup()
2.pycharm提供
python console
数据准备
import os
if __name__ == "__main__":
os.environ.setdefault("DJANGO_SETTINGS_MODULE", "Pythonexerciseday54_lianxi.settings")
import django
django.setup()
from app01 import models
models.User.objects.create(name='jason', age=18)
models.User.objects.create(name='tuzi', age=28)
models.User.objects.create(name='tony', age=38)
models.User.objects.create(name='kevin', age=48)
models.User.objects.create(name='oscar', age=58)
models.User.objects.create(name='stt', age=68)
models.User.objects.create(name='tian', age=78)
models.User.objects.create(name='tian2', age=78)
查询方法all()与filter()
all() 返回表里面所有的数据
# res = models.User.objects.all()# 返回user表里面所有的数据,会封装成一个个对象 QuerySet可以看成是列表套对象
filter() 筛选数据
filter()# 括号内填写筛选条件,不写相当于all() QuerySet可以看成是列表套对象
filter(pk=1) # 想通过主键筛选数据 可以直接写pk 会自动定位到当前表的主键字段 无需自己查看具体字段名称
filter(pk=1)[0] # 直接获取数据对象 QuerySet支持索引取值,但是django不支持使用,因为索引不存在会直接报错
filter(pk=1).first() # 获取结果集中第一个对象 使用自带的方法 推荐使用封装的方法,不会出现索引超出范围报错的情况
filter(pk=1,name='kevin').first() # filter 括号内支持传多个参数,逗号隔开,多个参数之间默认是and关系
filter().filter().filter().filter() # 只要是QuerySet对象就可以继续点对象方法(类似与jq的链式操作)
filter().last() # 获取结果集中最后一个对象
filter() 用法详细
# res = models.User.objects.filter()# 括号内填写筛选条件,不写相当于all() QuerySet可以看成是列表套对象
# res = models.User.objects.filter(pk=1) # 想通过逐渐筛选数据 可以直接写pk 会自动定位到当前表的主键字段 无需自己查看具体字段名称
# res = models.User.objects.filter(pk=1)[0] # 直接获取数据对象 QuerySet支持索引取值,但是django不支持使用,因为索引不存在会直接报错
# res = models.User.objects.filter(pk=1).first() # 获取结果集中第一个对象 使用自带的方法 推荐使用封装的方法,不会出现索引超出范围报错的情况
# res = models.User.objects.filter(pk=1,name='kevin').first() # filter 括号内支持传多个参数,逗号隔开,多个参数之间默认是and关系
# res = models.User.objects.filter().filter().filter().filter() # 只要是QuerySet对象就可以继续点对象方法(类似与jq的链式操作)
res = models.User.objects.filter().last() # 获取结果集中最后一个对象
orm常见关键字操作
values() 返回包含对象具体值的字典的QuerySet
values_list() 与values()类似,只是返回的是元组而不是字典。
distinct() 对查询集去重
order_by() 对查询集进行排序
exclude() 排除满足条件的对象
reverse() 反向排序
count() 统计结果集的个数
exists() 校验结果集中有没有数据
get() 直接获取数据对象
用法详细
'''values()'''
res = models.User.objects.all().values('name','pk') # QuerySet可以看成列表套字典<QuerySet [{'name': 'jason', 'pk': 1}]>
res = models.User.objects.values('name','pk') # QuerySet可以看成列表套字典 指定字段,all不写也表示从所有数据中操作
res = models.User.objects.filter(pk=2).values('name') # 可以看成是对结果集进行字段的截取
'''values_list()'''
res = models.User.objects.all().values_list('name', 'age') # QuerySet可以看成列表套元组<QuerySet [('jason', 18)]>
'''distinct()'''
res = models.User.objects.all().distinct() # 数据对象中如果包含主键,不可能去重
res = models.User.objects.values('name').distinct() # 这样可以进行去重操作,结果还是一个QuerySet
'''order_by()'''
res = models.User.objects.order_by('age') # 默认是升序
res = models.User.objects.order_by('-age') # 改为降序
res = models.User.objects.order_by('age','pk') # 也支持多个字段依次排序
'''exclude()'''
res = models.User.objects.exclude(name='jason') # 取反操作
'''reverse()'''
res = models.User.objects.reverse() # 不起作用
res = models.User.objects.order_by('age').reverse() # 只有在order_by排序之后才可以
'''count()'''
res = models.User.objects.count() # 统计结果集的个数
'''exists()'''
res = models.User.objects.exists() # 有数据就返回True
res = models.User.objects.filter(name='jason666').exists() # 校验结果集中有没有数据 有True 没有False
'''get()'''
res = models.User.objects.get(pk=1) # 直接获取数据对象,但是不推荐使用,因为条件不存在会立即报错