Django 模板层之标签 自定义过滤器及标签 模板的继承与导入 模型层之前期准备 ORM常用关键字
模板层之标签
if判断
if、elif、else
{% if 条件1(可以自己写也可以用传递过来的数据) %}
<p>今天又是周三了</p>
{% elif 条件2(可以自己写也可以用传递过来的数据) %}
<p>百日冲刺</p>
{% else %}
<p>没多少时间了!</p>
{% endif %}
在view视图层中定义视图函数
注意{{ }}主要与数据值相关 {% %}主要与逻辑相关
在前端使用模板语法
for循环
普通for循环
for循环可以使用到的参数 自带关键字forloop
{% for i in l1 %}
<p>{{ forloop }}</p>
{% endfor %}
{% for i in l1 %}
{% if forloop.first %}
<p>这是我的第一次循环哟{{ i }}</p>
{% elif forloop.last %}
<p>这是我的最后一次循环哟{{ i }}</p>
{% else %}
<p>我们是中间循环哟{{ i }}</p>
{% endif %}
{% empty %}
<p>你给我传的数据是空的无法循环取值(空字符串、空列表、空字典)</p>
{% endfor %}
结果展示
django模板语法取值操作>>>:只支持句点符
句点符既可以点索引也可以点键
{{ d1.hobby.2.a1 }}
要展示haha
会自动区分是键还是索引 可以点索引也可以点键
当复杂数据获取之后需要反复使用可以起别名 但别名仅限于在with里面使用
{% with d1.hobby.2.a1 as h %}
<a href="">{{ h }}</a>
{% endwith %}
自定义过滤器、标签及inclusion_tag(了解)
在做前后端不分离项目时能够用上
前期三步骤
如果想要自定义一些模板语法 需要先完成下列的三步骤战略
1.在应用下创建一个名字必须叫templatetags的目录
2.在上述目录下创建任意名称的py文件
3.在上述py文件内先编写两行固定的代码
from django import template
register = template.Library()
自定义过滤器(最大只能接收两个参数)
@register.filter(name='myadd')
def func1(a, b):
return a + b
{% load mytags %}
<p>{{ i|myadd:1 }}</p>
django过滤器最大只能接受两个参数
在py文件下自定义过滤器:
用之前需要加载过滤器:
自定义标签(参数没有限制)
# 参数 标签 标签名字
@register.simple_tag(name='mytag')
def func2(a,b,c,d,e):
return f'{a}-{b}-{c}-{d}-{e}'
自定义inclusion_tag(局部的html代码)
首先我们要事先在templatetags下的py文件定义好一个函数
# 自定义inclusion_tag(局部的html代码)
@register.inclusion_tag('menu.html',name='mymenu')
def func3(n):
html = []
for i in range(n):
html.append('<li>第%s页</li>'%i)
return locals()
menu.html:我们函数的返回值将会输入到这个html文件中。这个html不是完整的html,只包含一部分标签,可以理解成一个小组件。
name='mymenu':这是我们定义的inclusion_tag的名字,可以通过这个名字,调用函数func3。
menu.html内部代码:
menu.html接受到func3传来的列表
['<li>第1页</li>','<li>第2页</li>','<li>第3页</li>','<li>第4页</li>','<li>第5页</li>'....]
模板的继承与导入
模板的继承(重要)
什么是模板继承?
你需要事先在你想要使用的主页面上划定区域做好标记,之后在子页面继承的时候你就可以使用在主页面划定的区域,也就意味着,如果你不划定任何区域,那么你子页面将无法修改主页面内容
如何使用它的继承?
1.先在你想要继承的主页面上通过bolck划定你将来可能要改的区域,并做好标记
2.在子页面上继承extends,利用block自动提示选取你想要修改的内容区域标记名称
3.在子页面extends中写你要修改主页面标记区的代码
4.然后就可以让子页面的修改内容渲染到主页面的划定区域上
# 模板页面提前先写好将来可能要替换的内容
{% block 名字 %}
"""模板内容"""
{% endblock %}
# 新页面要基于模板页面替换的内容
{% extends 'html文件名' %}
{% block 名字 %}
"""子板内容"""
{% endblock %}
"""一般情况下母板中至少应该有三个区域使得扩展性更高!!! css content js"""
{% block css %}
<style>...</style>
{% endblock %}
{% block content %}
...
{% endblock %}
{% block js %}
<script>...</script>
{% endblock %}
'''子板中还可以使用母板的内容 {{ block.super }} '''
注意这里的content只是个名字,可以自行修改。
继承页可以修改content代码块的内容:
模板的导入(了解)
将页面的某一个局部当成模块的形式
哪个地方需要就可以直接导入使用即可
导入格式
{% include '导入html文件名' %}
模型层之前期准备
sqlite3缺点
自带的sqlite3数据库对时间字段不敏感 有时候会展示错乱
所以我们习惯切换成常见的数据库比如MySQL django orm并不会自动帮你创建库 所以需要提前准备好
时间字段补充
如下通过ORM添加了数据库的时间字段
有两种类型的时间字段:
auto_now: 每次操作数据都会自动更新当前时间(只要动表就更新时间)
auto_now_add: 创建数据自动获取当前时间并更新 后续修改不人为操作的情况下不会更新(只要不改时间字段,改其他字段不会触发更新)
添加双下str方法,易于查看对象:
django测试模型层
单独测试django某个功能层:
提示你定义好环境。
django默认情况下是要把项目跑起来测试,不支持单py文件测试。
如果想要测试某个py文件(主要models.py):
python console
测试环境1:pycharm提供的python console
特点:在终端测试无法保存
搭建测试环境
测试环境2:自己搭建(自带的test或者自己创建)
1.拷贝manage.py前四行
2.自己再加两行
import django
django.setup()
这里才可以单独导入模型层进行测试:
必须要把环境准备好,才能导入模型层:
不要随便改顺序,会报错
查看orm底层SQL语句
django orm底层还是SQL语句 我们是可以查看的
如果我们手上是一个QuerySet对象 那么可以直接点query查看SQL语句
ps:SQL语句查询到数据之后 会把数据封装进对象
对于create方法不能拿到queryset对象:
如果想查看所有orm底层的SQL语句,可以在Django项目的settings.py文件中,在最后复制粘贴如下代码:
LOGGING = {
'version': 1,
'disable_existing_loggers': False,
'handlers': {
'console':{
'level':'DEBUG',
'class':'logging.StreamHandler',
},
},
'loggers': {
'django.db.backends': {
'handlers': ['console'],
'propagate': True,
'level':'DEBUG',
},
}
}
ORM常用关键字
创建数据 返回值就是当前创建的数据对象,可以通过点的方式去获取数据对象里面具体的某个字段的值
1.当需要查询数据主键字段值的时候 可以使用pk忽略掉数据字段真正的名字
2.在模型类中可以定义一个__str__方法 便于后续数据对象被打印展示的是查看方便
3.Queryset中如果是列表套对象那么直接for循环和索引取值但是索引不支持负数
4.虽然queryset支持索引但是当queryset没有数据的时候索引会报错 推荐使用first
1.create()
创建数据 返回值就是当前创建的数据对象
ps:还可以利用类实例化对象然后调用save方法创建
2.update()
更新数据
3.delete()
删除数据
import os
def main():
os.environ.setdefault('DJANGO_SETTINGS_MODULE', 'djang04.settings')
import django
django.setup()
from app01 import models
print(models.User.objects.filter())
res = models.User.objects.create(name='kevin', age=38)
print(res)
user_obj = models.User(name='oscar', age=20)
user_obj.save()
# 对象可以通过点的方式取值
print(res.name)
print(res.age)
print(res.join_time)
# 获取主键
print(res.uid)
print(res.pk)
if __name__ == '__main__':
main()
查找主键的时候有俩中方式:
1.我们可以通过主键名去使用点的方式去获取
2.也可以通过点pk得方式去获取
查找数据对象的主键以后我们创建表的时候可能会创建好多表,那么每个表中的主键名可能不一样,我们在要获取表对象的主键得时候,需要知道表的主键名,使用pk的话它会自动帮我们去找
filter()
筛选数据 返回值是一个QuerySet(可以看成是列表套数据对象)
1.括号内不写查询条件 默认就是查询所有
2.括号内可以填写条件 并且支持多个 逗号隔开 默认是and关系
res = models.User.objects.filter(name='kevin', age=38)
print(res) # <QuerySet [<User: 对象:kevin>]>
all()
查询所有数据 返回值是一个QuerySet(可以看成是列表套数据对象)
res = models.User.objects.all()
print(res) # <QuerySet [<User: 对象:jason>, <User: 对象:kevin>, <User: 对象:tony>]>
first()
获取Queryset中第一个数据对象 如果为空则返回None
res = models.User.objects.all().first()
print(res) # 对象:jason
last()
获取Queryset中最后一个数据对象 如果为空则返回None
res = models.User.objects.all().last()
print(res) # 对象:tony
get()
直接根据条件查询具体的数据对象 但是条件不存在直接报错 不推荐使用
res = models.User.objects.get(pk=2)
print(res) # 对象:kevin
这个方法与filter方法对比:
res = models.User.objects.get(pk=2)
print(res) # 对象:kevin
res = models.User.objects.filter(pk=2).first()
print(res) # 对象:kevin
虽然看起来get方法可能更简单一点,但是不推荐使用get方法
当查询查询条件不存在的时候:
res = models.User.objects.get(pk=21)
print(res) # 直接报错
res = models.User.objects.filter(pk=21).first()
print(res) # None
values()
指定查询字段 结果是Queryset(可以看成是列表套字典数据)
res = models.User.objects.values()
print(res) # <QuerySet [{'uid': 1, 'name': 'jason', 'age': 18, 'join_time': datetime.date(2022, 9, 5)}, {'uid': 2, 'name': 'kevin', 'age': 38, 'join_time': datetime.date(2022, 9, 5)}, {'uid': 3, 'name': 'tony', 'age': 19, 'join_time': datetime.date(2022, 9, 5)}]>
value_list()
指定查询字段 结果是Queryset(可以看成是列表套元组数据)
order_by()
指定字段排序 默认是升序 在字段前加负号则为降序 并且支持多个字段排序
res = models.User.objects.order_by('age')
print(res) # <QuerySet [<User: 对象:jason>, <User: 对象:tony>, <User: 对象:kevin>]>
res = models.User.objects.order_by('-age')
print(res) # <QuerySet [<User: 对象:kevin>, <User: 对象:tony>, <User: 对象:jason>]>
count()
统计orm查询之后结果集中得数据格式
res = models.User.objects.all().count()
print(res) # 3
distinct()
针对重复的数据进行去重 一定要注意数据对象中的主键
exclude()
针对括号内的条件取反进行数据查询QuerySet(可以看成是列表套数据对象)
res = models.User.objects.exclude(pk=2)
print(res) # <QuerySet [<User: 对象:jason>, <User: 对象:tony>]>
reveres()
针对已经排了序的结果做颠倒
exists()
判断查询结果集是否有数据 返回布尔值 但是几乎不用因为所有数据自带布尔值