首页 > 其他分享 >模板层之标签、自定义模板语法、母版(模版)的继承与导入、模型层前期准备知识点、ORM常用关键字

模板层之标签、自定义模板语法、母版(模版)的继承与导入、模型层前期准备知识点、ORM常用关键字

时间:2022-12-14 20:11:38浏览次数:47  
标签:知识点 自定义 models res html objects User 模板

模板层之标签

模板语法支持if判断(支持elif):

{% if 条件1(可以自己写也可以用传递过来的数据) %}
        <p>今天又是周三了</p>
{% elif 条件2(可以自己写也可以用传递过来的数据) %}
        <p>百日冲刺</p>
{% else %}
        <p>没多少时间了!</p>
{% endif %}

image

模板语法支持for循环,有一个特殊的关键字forloop:
image
first 键只有在是第一次循环时才是True
last 键只有在是最后一次循环时才是false
counter0 从0开始计数
counter 从1开始计数

for循环的示例:

{% for k in t1 %}
        {% if forloop.first %}
            <p>这是我的第一次循环{{ k }}</p>
        {% elif forloop.last %}
            <p>这是我的最后一次循环{{ k }}</p>
        {% else %}
            <p>这是中间循环{{ k }}</p>
        {% endif %}
        
        {% empty %}
            <p>你给我传的数据是空的无法循环取值(空字符串、空列表、空字典)</p>
{% endfor %}

image
结果:
image
for循环的empty分支:
如果传的数据支持for循环,但是里面没有数据值,这时候会走empty分支。
image
写前后端分离项目时,不会使用模板语法。

django模板语法取值操作 >>> 只支持句点符

django模板语法取值操作>>>:只支持句点符
    句点符既可以点索引也可以点键
	 {{ d1.hobby.2.a1 }}

示例:
image
对于这种字典套列表的数据,可以这样取值:
image
也就是说,以点的方式取值既可以点索引也可以点键。django会自己取去判断点的后面是索引还是键。

如果对象中的某个值要多次使用:
可以取别名:

{% with d1.hobby.2.a1 as h %}  
        <a href="">{{ h }}</a>
{% endwith %}

image
只有在with代码块之内可以使用as取的别名。

自定义模板语法

前期准备

如果想要自定义一些模板语法 需要先完成下列的三步:

  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文件下自定义过滤器:
image
用之前需要加载过滤器:image

自定义标签

相当于自定义函数,其参数没有限制

# 自定义标签(参数没有限制)
@register.simple_tag(name='mytag')
def func2(a, b, c, d, e):
    return f'{a}-{b}-{c}-{d}-{e}'
{% load mytags %}
{% mytag 'jason' 'kevin' 'oscar' 'tony' 'lili' %}

image
支持传多个参数:
image

自定义inclusion_tag

首先我们要事先在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内部代码:
image
menu.html接受到func3传来的列表:

['<li>第1页</li>','<li>第2页</li>','<li>第3页</li>','<li>第4页</li>','<li>第5页</li>'....]

使用过滤器{{ liStr|safe }},将字符串变成真的html代码。
最后传递到原html页面使用,还可以指定参数(这个参数对应函数形参n):
image
效果:
image

模板的继承与导入

引入

我们经常可以看到这样的网站:
image
点击登录--->导航条 和 侧边栏不变 右边变成登录的页面
也就是说页面中有固定不动的部分和动态变化的部分。
多个页面有很多相似的地方 我们可以采取下列方式:
方式1:传统的复制粘贴
方式2:模板的继承

模板的继承

模板的继承只需要一行模板语法就可以做到。
假如home.html是我们的母模板,则先将子板的html代码清空,再加入代码:
{% extends 'home.html' %}
就可以实现继承。

划定子板可修改的区域 block

django模板语法支持在继承的前提上修改,这时候需要在母板上提示哪些部分可以修改:
image
语法:{% block 区域名称 %}
注意这里的content只是个名字,可以自行修改。
继承页可以修改content代码块的内容:
image
继承页在content编写的html会把母板写的替换掉。

母模板中至少应该标明三个区域:
页面内容、CSS样式区、JS代码区

给子模板预留出加载CSS代码 加载JS代码的区域。
这样子版可以自己编辑CSS\JS代码,更加灵活。

子板加载自己的JS代码:
image
子板加载自己的CSS代码:
image
这样子页面不仅可以用主页的html,还可以有自己的样式和JS代码。

在模板的基础上扩展 super

super方法,可以在模板原有的基础上扩展(可以保留母板的html代码)(并且可以连续用多次):
image

组件的导入

写一个html组件(不是完整的html页面)
把这个组件导入页面。
image
使用include可以直接导入html代码(需要提前写好一个固定的html组件页面):
image

模型层之前期准备

sqlite3缺点

  1. 自带的sqlite3数据库对时间字段不敏感 有时候会展示错乱
    所以我们习惯切换成常见的数据库比如MySQL django orm并不会自动帮你创建库 所以需要提前准备好

时间字段补充

如下通过ORM添加了数据库的时间字段
image
有两种类型的时间字段:
auto_now: 每次操作数据都会自动更新当前时间(只要动表就更新时间)
auto_now_add: 创建数据自动获取当前时间并更新 后续修改不人为操作的情况下不会更新(只要不改时间字段,改其他字段不会触发更新)
添加双下str方法,易于查看对象:
image

django测试模型层

单独测试django某个功能层:
image
提示你定义好环境。
django默认情况下是要把项目跑起来测试,不支持单py文件测试。
如果想要测试某个py文件(主要models.py):

python console

测试环境1:pycharm提供的python console
image
特点:在终端测试无法保存

搭建测试环境

测试环境2:自己搭建(自带的test或者自己创建)

1.拷贝manage.py前四行
2.自己再加两行
	import django
	django.setup()

这里才可以单独导入模型层进行测试:
image
必须要把环境准备好,才能导入模型层:
image
不要随便改顺序,会报错。

查看orm底层SQL语句

django orm底层还是SQL语句 我们是可以查看的
如果我们手上是一个QuerySet对象 那么可以直接点query查看SQL语句
image
ps:SQL语句查询到数据之后 会把数据封装进对象

对于create方法不能拿到queryset对象:
image
如果想查看所有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.create()

创建数据并直接获取当前创建的数据对象

res = models.User.objects.create(name='阿兵', age=28)
res = models.User.objects.create(name='oscar', age=18)
res = models.User.objects.create(name='jerry', age=38)
res = models.User.objects.create(name='jack', age=88)
print(res)

image

2.filter()

根据条件筛选数据
结果是QuerySet [数据对象1,数据对象2]

res = models.User.objects.filter()
res = models.User.objects.filter(name='jason')
res = models.User.objects.filter(name='jason', age=19)  # 括号内支持多个条件但是默认是and关系

image
查询到一个对象的情况:
image
括号内支持多个条件,条件之间是and关系:
image

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

queryset不支持负索引:
image
queryset推荐使用first\last、这跟直接使用索引0有什么区别?
原因是查询不到会报错!
image
使用first就不会报错,返回一个None。
image
last用于替代负数索引。补充说明queryset列表使支持切片的。

4.update()

更新数据(批量更新)
models.User.objects.filter().update()     批量更新
models.User.objects.filter(id=1).update() 单个更新

更新filter筛选出来的所有数据!筛出来一个就更新一个,筛出来一群就更新一群。

5.delete()

删除数据(批量删除)

models.User.objects.filter().delete()      批量删除
models.User.objects.filter(id=1).delete()  单个删除

这些方法都是queryset对象的方法。

6.all()

查询所有数据
结果是QuerySet [数据对象1,数据对象2]注意这里是列表

res = models.User.objects.all()

7.values()

根据指定字段获取数据(想匹配获取多个对象中的数据) 结果是QuerySet [{},{},{},{}]注意这里是列表套字典
image
上述这三种写法效果一样:
image
获取一个字段时的queryset对象:
image
ps:列表套字典,但还是queryset对象。
queryset对象支持for循环:
image

8.values_list()

根据指定字段获取数据 结果是QuerySet [(),(),(),()] 注意是列表套元祖

res = models.User.objects.all().values_list('name','age')

image
获取所有数据的name和age字段

9.distinct()

去重(对结果集进行去重、不会删除原数据)
数据一定要一模一样才可以 如果有主键肯定不行

res = models.User.objects.values('name','age').distinct()

数据库中含有两个相同的字段:(主键不相同)
image
无法去重:
image
这个去重是针对于拿到的字段对象用的(不包含主键)
image

10.order_by()

根据指定条件排序 默认是升序 字段前面加负号就是降序

res = models.User.objects.all().order_by('age')
print(res)

默认按照升序排序:
image
改降序:加减号
image
支持写多个排序条件

11.get()

根据条件筛选数据并直接获取到数据对象 一旦条件不存在会直接报错 不建议使用

res = models.User.objects.get(pk=1)
print(res)
res = models.User.objects.get(pk=100, name='jason')
print(res)

get直接获取到数据对象
image
条件一旦不存在,直接报错:
image
和之前一样,多个查询条件之间的关系是and。

12.exclude()

取反操作

res = models.User.objects.exclude(pk=1)
print(res)

exclude取反操作:
不要主键等于1的数据。
image
查看SQL:
image

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)

reverse颠倒顺序:
image
使用这个方法必须有个前提,被操作的对象必须已经排过序。否则不会颠倒顺序。

14.count()

统计结果集中数据的个数

res = models.User.objects.all().count()
print(res)

image

15.exists()

判断结果集中是否含有数据 如果有则返回True 没有则返回False

res = models.User.objects.all().exists()
print(res)
res1 = models.User.objects.filter(pk=100).exists()
print(res1)

image

标签:知识点,自定义,models,res,html,objects,User,模板
From: https://www.cnblogs.com/wwssadadbaba/p/16983393.html

相关文章