进入python的世界_day52_Django之模板层(继承、标签)、模型层(ORM关键字)
一、模板层——标签*
1.分支结构
{% %}
# if...elif..else
eg 视图层:
def index_func(request):
l1 = [1, 2, 3, 4, 5]
a = '天气不错'
c = {'city': 'shanghai'}
return render(request, 'indexPage.html',locals())
模板层:
# 条件 一般是模板语法传过来的数据 直接写名字就行 不需要双大括号
<body>
{% if 5 in l1 %}
<p>确实存在5</p>
{% elif 10 not in l1%}
<p>确实不存在10</p>
{% else %}
<p>我什么时候执行呢?他们都不成立就是我</p>
{% endif %}
</body>
# for 循环 输入for按tab自动补全格式
{% for i in l1 %}
<p>{{i}}</p>
{% endfor %}
# 有一个东西补充下,forloop,有一些特性,可以点出来
{% for i in l1 %}
{% if forloop.first %}
<p>我是循环的第一个</p>
{% elif forloop.last %}
<p>我是循环的最后一个</p>
{% else %}
<p>{{i}}</p>
{% endif %}
{% endfor %}
>>>
我是循环的第一个
2
3
4
我是循环的最后一个
2.多级拿值
django只能句点符取值,算是好处,因为索引直接点也可以用,不用写[]
eg 视图层:
def index_func(request):
l1 = [1, 2, 3, 4, {'city': 'shanghai', 'name': ['jack', 'rose', 'tony']}]
a = '天气不错'
return render(request, 'indexPage.html',locals())
模板层:
比如说,我想拿到tony
{{l1.4.name.2 }} # >>> tony
另外,也支持把拿到的值拿一个变量名接收下,在with框中就可以随意使用,注意不能离开with框
<p>
{% with l1.4.name.2 as f %} # f就是tony了
<p>{{ f}}</p>
<p>{{ f}}</p>
<p>{{f|add:'老师' }}</p> # 昨天学的拼接
{% endwith %}
</p>
>>>
# tony
# tony
# tony老师
二、自定义标签、过滤器、inclusion_tag
1.必备前提
- 在应用下创建名为templatetags文件夹
- 在该文件夹创建任意名称的py文件
- 在该py文件内编写自定义固定代码,然后参照着自带的过滤器格式自己就可以开始编写自创的过滤器或者标签了(其实就是函数)
- 注意,过滤器只能接收两个参数,只能两个参数,即|左边一个,右边一个,如果只想接收一个参数,后面的参数=None即可
# 自定义过滤器
from django import template
register = template.Library() # 注意是首字母大写的Library
@register.filter(name='happy') # name随便起,待会就是用这个
def happy(a, b):
return a ** b
写好后,在模板层要加载下哦~
eg 视图层:
def index_func(request):
l1 = [1, 2, 3, 4, {'city': 'shanghai', 'name': ['jack', 'rose', 'tony']}]
a = '天气不错'
c = {'city': 'shanghai'}
d = 10
b = 2
return render(request, 'indexPage.html', locals())
{% load myhappy %}
<p>
{{d|happy:b}}
</p>
>>> # 等于d**b=10**2=100
5.自定义标签的函数参数就没有限制,想几个就几个
# 自定义标签
还是在自己创的py文件内
@register.simple_tag(name='funny')
def funny(a, b, c):
import datetime
d1 = f'{a}-{b}-{c}'
d2 = f'{a}-12-31'
date1 = datetime.datetime.strptime(d1, "%Y-%m-%d").date()
date2 = datetime.datetime.strptime(d2, "%Y-%m-%d").date()
a1 = (date2 - date1).days
return f'今天是{a}年{b}月{c}日,距离今年结束还有{a1}天'
eg 视图层:
def index_func(request):
import datetime
todaytime = datetime.datetime.today()
a = todaytime.year
b = todaytime.month
c = todaytime.day
return render(request, 'indexPage.html', locals())
模板层:
{% load myhappy %}
<body>
{% funny a b c %}
</body>
>>>
# 今天是2022年12月14日,距离今年结束还有17天
2.自定义inclusion_tag
不是很常用,意思是在页面上调用这个玩意,会触发函数的运行,函数运行后得到一些数据,数据被传给一个不完整的页面。在该页面渲染好了再给到最开始的页面
用于自动化产生有序无序列表
# 自定义inclusion_tag
还是在自己创的py文件内
@register.inclusion_tag('ohhh.html', name='myohhh')
def myfunc(n):
html = []
for i in range(n):
html.append('<li>第%s页</li>' % i)
return locals()
另外一个不完整的页面:
<ul>
{% for i in html %}
{{i|safe}} # safe是信任被传过来的东西,能直接加载
{% endfor %}
</ul>
模板层:
{% myohhh 20 %}
三、母板的继承与导入***
1.继承***
用了以后就非常方便,能让不同的页面继承另外的母页面的所有东西,同时具备有在复制的这份页面上做出改动的资格
#继承 母板内容
#母板先配置
{% block 名字 %} # 名字尽量能见名知意
模板内容
{% endblock %}
# 子板的使用
{% extends 'html文件名' %} # 子板继承了 就可以 获取的 该文件 所有内容,就相当于复制了一份
{% block 名字 %} #找到标记
子板内容
{% endblock %}
一般情况下母板中至少应该有三个区域使得扩展性更高!!!
页面内容区,CSS编辑区,JS编辑区
{% block css %}
...
{% endblock %}
{% block content %}
...
{% endblock %}
{% block js %}
...
{% endblock %}
{子板中 可以使用母版的内容}
# 这样子板就看着简单明了,能编辑自己的样式、动态、内容又不冲突母板
# 补充:子板也可以使用{{block.super}},可以多次叠加,意思就是多次叠加该标记段
{% block content %}
{{ block.super}}
...
...
{% endblock %}
2.模板的导入(了解)
将某一个Html或者某一块html当做模块的形式导入使用
关键字:
{% include '网址'%}
四、模型层之ORM常见关键字
模型层,因为要和数据打交道,所以我们得提前准备好表表的创建django自带 一个sqlite3 小型数据库,但是该数据库功能非常有限 并且针对日期类型的数据兼容性很差,所以我们基本不使用sqlite3,而是换成mysql之类的数据库
使用django ORM前,库得我们自己先准备好
# cmd运行
# 进入mysql
show databases
create database 库名
不要忘了选择自己的数据库后,去改django配置文件里面的数据库的相关配置
DATABASES = {
'default': {
'ENGINE': 'django.db.backends.sqlite3',
'NAME': os.path.join(BASE_DIR, 'db.sqlite3'),
}
}
# 改为
DATABASES = {
'default': {
'ENGINE': 'django.db.backends.mysql',
'NAME': 'djday05', # 你要使用的库
'USER': 'root',
'PASSWORD': 'xxx', # 你的密码
'HOST': '127.0.0.1',
'PORT': 3306,
'CHARSET': 'utf-8',
}
}
配置好了后,可以开始写ORM了,先去models.py下创建表,写几个字段
先学两个新的ORM 单词
DateTimeField # 年月日时分秒
DateTime # 年月日
verbose_name= # 别名
时间单词附带的参数有{
auto_now= # 每次操作数据都会更新时间
auto_now_add= # 只记入首次创建该数据的时间
}
models.DateTimeField (verbose_name='',auto_now_add=True)
# _________________________________________
class Userinfo(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)
edit_time = models.DateTimeField(verbose_name='编辑时间', auto_now=True)
def __str__(self): # 当对象被执行打印操作时自动触发,打印其中的返回值
return f'用户对象{self.name}'
django中,任何操作了数据库数据的动作后,都要同步一下数据库数据,要执行那两条命令
python manage.py makemigrations
python manage.py migrate
单独测试django的某个功能层
如果想添加数据,想起来前几天的开路由,写视图函数,函数做判断,才能搞进去一条数据,太麻烦了,不知道有没有能单独测试我这个py文件的功能
如果想要测试某个py文件,可以用测试环境
第一种:
这个是纯天然pycharm自带的,不过不保存,关了后代码就消失了
第二种:
自己搭建,代码能长久保存,方便不同时间段再来测试,必须环境准备好后再导模块哦
# 任意位置开一个py文件,复制根目录的manage.py文件的亮着的前四行代码
# 然后自己加上两行,这样共计六行代码
import os
import sys
def main():
os.environ.setdefault('DJANGO_SETTINGS_MODULE', 'day05.settings')
import django
django.setup()
# 接下来就可以导入models 然后开始测试,因为是封了一个函数,得调用函数哦~
main()
ORM常用关键字
### 拓展:
可以在settings里加一份配置,每次执行ORM都会打印底层SQL给到终端显示
LOGGING = {
'version': 1,
'disable_existing_loggers': False,
'handlers': {
'console':{
'level':'DEBUG',
'class':'logging.StreamHandler',
},
},
'loggers': {
'django.db.backends': {
'handlers': ['console'],
'propagate': True,
'level':'DEBUG',
},
}
}
1.create()
2.filter()
结果是一个QuerySet的玩意是列表套数据对象,如果要拿,要索引,索引后可以直接句点符来点数据
括号内的条件,是and 的关系,筛选时要同时满足多个条件才能筛选成功
3.first()last()
last=索引[-1] 注意,ORM不支持负数索引,所以有时候可以用一下last
更加有用的是,这两个的附加后,如果filter筛选了空列表,不会报错,而直接索引会报错!
4.update()
能批量更新,也可以单个更新
5.all()
查询所有数据=filter()
6.values()
根据指定字段获取数据,就是只拿每一行数据的某个字段,很多行就会组成QuerySet列表套字典返回
res.query可以查看底层SQL语句
其实就是 select name from userinfo
7.values_list()
也是根据指定字段获取数据 结果是QuerySet [(),(),(),()]
8.distinct()
去重,数据一定要一模一样才可以,一定注意主键
另外,如果是基于查询去重,是把查询的结果去重,而不是把原数据真的给删了
9.order_by()
指定字段排序,默认升序排序,也可以给条件加-号,就是降序排序
10.count()
统计ORM查询之后结果集中的数据个数
11.get()
根据条件筛选数据,并直接获取数据对象(意思就不是啥QureySet的玩意了),条件一旦不存在,直接报错
12.exclude()
针对括号内的条件取反进行数据查询,依旧返回 QuerSet这玩意(可以看成是列表套数据对象)
13.reverse()
针对已经排了序的结果做颠倒,有点难用,必须是已经排序过的结果才能用这个颠倒 15.exists()
判断结果集中是否含有数据 如果有则返回True 没有则返回False,没啥用
res = models.Userinfo.objects.all().exists()
print(res) >>> True
res1 = models.Userinfo.objects.filter(pk=999).exists()
print(res1) >>> False