模板层语法、模板层之标签、模板的继承与导入、模型层之ORM常见关键字
一、模板层语法
1.模板语法的传值
urls代码:
path('modal/', views.modal)
views代码:
def modal(request):
name = 'jason'
return render(request, 'modal.html', {'name':name})
指名道姓传参 不浪费资源
html代码:
<body>
{{ name }}
{{ age }}
{{ gender }}
</body>
urls代码:
path('modal/', views.modal)
views代码:
def modal(request):
name = 'jason'
age = 18
gender = 'female'
return render(request, 'modal.html', locals()) # 将函数体里局部空间里所有的名字全部传入给前面的那个页面
将整个局部名称空间中的名字去全部传入简单快捷
2.模板语法传值特性
1.基本数据类型正常展示
2.文件对象也可以展示并调用方法
3.函数名会自动加括号执行并将返回值展示到页面上(不支持额外传参)
4.类名也会自动加括号调用
5.对象则不会
ps:总结针对可以加括号调用的名字模板语法都会自动加括号调用
3.模板语法传值的范围
基本数据类型直接传值使用
views代码:
def modal(request):
i = 123
f = 13.4
s = 'study work hard'
d = {'name': 'Tony', 'pwd': 123}
t = (11, 22, 33)
se = {11, 22, 33}
b = True
return render(request,'modal.html',locals())
html代码:
<p>{{ i }}</p>
<p>{{ f }}</p>
<p>{{ s }}</p>
<p>{{ l }}</p>
<p>{{ d }}</p>
<p>{{ t }}</p>
<p>{{ se }}</p>
<p>{{ b }}</p>
函数名的传递会自动加上括号执行并将返回值展示到页面上,模板语法时不支持有参函数的
def modal(request):
def func():
print('函数')
return '从这里才能传值过去哦'
return render(request,'modal.html',locals())
<p>{{ func }}</p>
4.模板语法过滤器(类似于Python内置函数)
1.模板语法过滤器
过滤器就类似于模板语法的内置方法
模板语法提供了一些内置方法,以助于快速的处理数据(过滤器最多只能有两个参数)
2.基本语法
{{变量|过滤器:参数}}
过滤器:会自动将竖杠左侧的变量当做第一个参数交给过滤器处理,右侧的当做第二个参数。
'''
django模板语法中的符号就两个 一个{{}} 一个{%%}
需要使用数据的时候 {{}}
需要使用方法的时候 {%%}
'''
<p>统计长度:{{ s|length }}</p>
# 统计长度:15
<p>加法运算:{{ i|add:123 }}、加法运算:{{ s|add:'heiheihei' }}</p>
# 加法运算:246、字符串加法运算:study work hard +every day
<p>日期转换:{{ s|date:'Y-m-d H:i:s' }}</p>
<p>文件大小:{{ file_size|filesizeformat }}</p>
# 文件大小:31.1 KB
<p>数据切片:{{ l|slice:'0:10' }}</p>
# 切片操作(支持步长)
<p>字符截取(三个点算一个):{{ s1|truncatechars:6 }}</p>
# 字符截取(包含三个点):模板语法提供...
<p>单词截取(空格):{{ s1|truncatewords:6 }}</p>
# 单词截取(不包含三个点 按照空格切):my name is objk my age is 18 and ...
<p>语法转义:{{ script_tag }}</p>
# <h1>今晚吃了好多好吃的</h1>(是不会识别前端标签的)
<p>语法转义:{{ script_tag|safe }}</p>
# 今晚吃了好多好吃的
# 如果不转移的话,那么无法识别前端标签,那么以下这种功能的情况就没有办法实现
<p>语法转义:{{ script_tag1|safe }}</p>
script_tag1 = '<script>alert(666)</script>'
# 也可以使用后端转
from django.utils.safestring import mark_safe
script_tag2 = '<script>alert(666)</script>'
res = mark_safe(script_tag2)
ps:有时候html页面上的数据不一定非要在html页面上编写了 也可以后端写好传入
二、模板层之标签(类似于Python流程控制)
1.if判断
{% if 条件1(可以自己写也可以用传递过来的数据) %}
<p>xxxxx</p>
{% elif 条件2(可以自己写也可以用传递过来的数据) %}
<p>xxxxxx</p>
{% else %}
<p>没多少时间了!</p>
{% endif %}
eg:
{% if b %}
<p>今天又是周三了,好好学习啊</p>
{% elif n %}
<p>加油加油</p>
{% else %}
<p>相信自己,可以的</p>
{% endif %}
2.for循环
forloop模板语法自带的变量名
{% for k in t1 %}
{% if forloop.first %}
<p>这是我的第一次循环{{ k }}</p>
{% elif forloop.last %}
<p>这是我的最后一次循环{{ k }}</p>
{% else %}
<p>这是中间循环{{ k }}</p>
{% endif %}
{% empty %}
<p>empty专门用来判断空的,传的是空的无法循环取值(空字符串,空列表,空字典)</p>
{% endfor %}
eg:
{% for k in t1 %}
{% if forloop.first %}
<p>这是第一次循环</p>
{% elif forloop.last %}
<p>这是最后一次循环</p>
{% else %}
<p>{{ i }}</p>
{% endif %}
{% empty %}
<p>empty专门用来判断空的,传的是空的无法循环取值(空字符串,空列表,空字典)</p>
{% endfor %}
3.with语法起别名
{% with d.hobby.3.a1 as n %}
<p>{{ n }}</p>
在with语法内可以通过as后面得别名快速使用前面非常复杂获取数据的方式
<p>{{ d.hobby.3.a1 }}</p>
{% endwith %}
ps:
可以通过as后面得别名快速的使用前面非常复杂获取数据的方式
密码规范:只能with代码块的范围之内才能使用别名
三、自定义过滤器、标签及inclusion_tag
1.自定义一些模板语法 先完成下列的三步走战略
1.在应用下创建一个名字必须叫templatetags的目录
2.在上述目录下创建任意名称的py文件
3.在上述py文件内先编写两行固定的代码
2.自定义过滤器filter,最多有两个参数
from django import template
register = template.Library()
# 自定义过滤器,最大只能接收两个参数
# 参数 过滤器 过滤器名字
@register.filter(name='myfilter')
def my_add(a,b):
return a + b
{% load first %}
<p>{{ i|myfilter:1 }}</p>
3.自定义标签(函数)
# 参数 标签(函数)标签(函数)名字
@register.simple_tag(name='nt')
def my_add(a,b,c,d):
return a + b + c + d
{% load first %}
{% nt 1 2 3 4 %}
4.自定义inclusion_tag页面
# 自定义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() # 将html传给name的页面,在哪个页面上使用
{% load mytags %}
{% mymenu 20 %}
四、模板的继承与导入
1.模板的继承
模板继承是 Django 模板语言中最强大的部分。模板继承使你可以构建基本的“骨架”模板,模板继承大大提高了代码的可重用性,减轻开发人员的工作量。
2.任何使用模板的继承
1.在模板的使用block规划子板以后要修改的区域,并做好标记
2.在子页面上继承extend,利用block自动选取你想要修改的内容区域标记名称
3.在子页面extend中写您想要修改主页面标记区的代码
4.然后让子页面的修改内容渲染到主页面的规定区域上
# 模板页面提前写好将要替换的内容
{% block 区域名称 %}
{% endblock %}
# 子板继承模板
{% extend 'html文件'%}
{% block 区域名称 %}
'''子板内容'''
{% endblock %}
{% block css %}
'''子板内容'''
{% endblock %}
{% block js %}
'''子板内容'''
{% endblock %}
'''子板可以继续使用模(母)板的内容'''
3.模板的导入
将某个html的部分提前写好 之后很多html页面都想使用就可以导入
{% include 'myform.html' %}
五、表查询数据准备及测试环境搭建
1.djaingo自带一个sqlite3小型数据库
自带的sqlite3数据库对于时间字段不敏感,有时候会展示错乱
sqlite3是pycharm自带的数据库,不用额外安装模块,操作简单
python + mysql = SQLite
2.djiango切换到MySQL数据库
DATABASES = {
'default': {
'ENGINE': 'django.db.backends.mysql',
'NAME': 'day05',
'USER': 'root',
'PASSWORD': '123',
'HOST': '127.0.0.1',
'PORT': 3306,
'CHARSET':'utf8'
}
}
3.定义模型类
from django.db import models
# Create your models here.
class User(models.Model):
name = models.CharField(max_length=32,verbose_name='用户名')
age = models.IntegerField(verbose_name='年龄')
register_time = models.DateTimeField(verbose_name='注册时间',auto_now_add=True)
def __str__(self):
return f'用户对象{self.name}'
'''
针对时间字段有两个重要的参数:
auto_now:每次操作数据都会自动更新当前时间
auto_now_add:创建数据自动获取当前的时间,后续不人为操作的情况下不会更新
'''
4.执行数据库迁移命令(模型类>>>表)
python mange.py makemigrations
python mange.py migrate
5.模型层测试环境准备
方式一:
'''复制mange.py文件的前四行代码 放入一个空白的py文件中 但是不要放入已有的文件中'''
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())
if __name__ == '__main__':
main()
方式二:
python console命令行测试环境
终端的形式 代码没法保存下来 电话关掉以后 代码就会没有了 只是临时的
六、ORM常见关键字
1.create()
创建数据并直接获取当前创建的数据对象
res = models.User.objects.create(name='jason',age=18)
res = models.User.objects.create(name='jia',age=17)
res = models.User.objects.create(name='wei',age=28)
res = models.User.objects.create(name='xin',age=38)
res = models.User.objects.create(name='roy',age=48)
res = models.User.objects.create(name='jackson',age=58)
2.filter()
根据条件筛选数据,结果是QuerySet [数据对象1,数据对象2]
res = models.User.objects.filter()
res = models.User.objects.filter(name='jason')
3.first() last()
QuerySet支持索引取值但是只支持正数 并且orm不建议你使用索引
res = models.User.objects.filter()[1]
res = models.User.objects.filter(pk=100)[0] # 数据不存在索引取值会报错
res = models.User.objects.filter(pk=100).first() # 数据不存在不会报错而是返回None
res = models.User.objects.filter().last() # 数据不存在不会报错而是返回None
4.update()
models.User.objects.filter().update() 批量更新
models.User.objects.filter(id=1).update() 单个更新
5.delete()
models.User.objects.filter().delete() 批量删除
models.User.objects.filter(id=1).delete() 单个删除
6.all()
models.User.objects.filter().all() 查询所有数据
结果是QuerySet [数据对象1,数据对象2]
7.values()
res = models.User.objects.all().values('name')
res = models.User.objects.filter().values('name')
res = models.User.objects.value('name')
结果是QuerySet [{},{},{}]
8.values_list()
res = models.User.objects.values_list('name')
根据指定字段获取数据 结果是QuerySet [(),(),(),()]
9.distinct()
res = models.User.objects.values('name','age').distinct()
去重 数据一定要一模一样才可以 如果有主键肯定不行
10.order_by()
models.User.objects.filter().all().order_by()
根据指定条件排序 默认是升序 字段前面加负号就是降序
11.get()
models.User.objects.get(pk=1)
根据条件筛选数据并直接获取到数据对象 一旦条件不存在会直接报错 不建议使用
12.exclude()
res = models.User.objects.exclude(pk=1)
取反操作
# 颠倒顺序(被操作的对象必须是已经排过序的才可以)
# res = models.User.objects.all()
# res = models.User.objects.all().order_by('age')
# res1 = models.User.objects.all().order_by('age').reverse()
# print(res, res1)
# 14.count() 统计结果集中数据的个数
# res = models.User.objects.all().count()
# print(res)
# 15.exists() 判断结果集中是否含有数据 如果有则返回True 没有则返回False
res = models.User.objects.all().exists()
print(res)
res1 = models.User.objects.filter(pk=100).exists()
print(res1)
13.reverse()
颠倒顺序(被操作的对象必须是已经排过序的才可以)
res = models.User.objects.all()
res = models.User.objects.all().order_by('age')
res1 = models.User.objects.all().order_by('age').reverse()
print(res, res1)
14.count()
统计结果集中数据的个数
res = models.User.objects.all().count()
15.exists()
判断结果集中是否含有数据 如果有则返回True 没有则返回False
res = models.User.objects.all().exists()
print(res)
res1 = models.User.objects.filter(pk=100).exists()
print(res1)
返回QuerySet对象的方法有
all()
filter()
exclude()
order_by()
reverse()
distinct()
特殊的QuerySet
values() 返回一个可迭代的字典序列
values_list() 返回一个可迭代的元祖序列
返回具体对象的
exists()
返回数字的方法
count()