P08 QuerySet 和 Instance
QuerySet
Django 的 ORM(Object-Relational Mapping,对象-关系映射)是一个非常强大的工具,它帮助你管理和查询数据库。ORM 能够让你使用Python(或其他编程语言)来操作数据库,就像你在操作Python对象一样。ORM用到三个类:Manager、QuerySet、Model。
从数据库中查询出来的结果一般是一个集合,这个集合叫做 QuerySet。
Django的ORM通过Model的objects属性提供各种数据操的接口(API),并通过 Model.objects 方法返回QuerySet,生产符合查询条件的列表,列表中包含多个 Instance。
QuerySet 的正式定义
class QuerySet(model=None, query=None, using=None)[source]
QuerySet 的两大特色
(1) 惰性:若这个对象中包含了需要的数据且需要使用时,它会去DB中获取数据,否则不会获取。 比如说在内部,创建、 过滤、切片和传递一个QuerySet,而没有进行真正的数据执行,不会真实操作数据库,被称为惰性。(2)缓存使用同一个查询集,第一次使用时会发生数据库的查询,然后Django会把结果缓存下来,再次使用这个查询集时会使用缓存的数据,减少了数据库的查询次数。
QuerySet 的 API 方法
all()
:返回模型的所有对象filter()(**kwargs)
用于返回符合条件的所有数据get()
方法与filter()
的作用类似,用于返回符合条件的单个对象但是可能会返回多个值delete()
:可以删除符合条件的所有对象update()
:将符合条件的所有对象的某个字段值进行更新create()
是save()
方法的快捷方式,用于创建并保存一个新的对象count()
:返回符合条件的对象数量order_by()
:对返回的对象进行排序,默认为升序。降序则在字段名前面加负号values()
:用来指定提取的数据中需要提取哪些字段
调用方法是:模型名.objects.方法名
比如views.py中的代码示例
queryset = GoodsCategory.objects.all()
category, created = GoodsCategory.objects.get_or_create(name=category_name)
goods = Goods.objects.filter(category=goods_category)
Instance
Instance指的是一个 Django 模型的单个实例,也就是数据库中的一行数据。相比于 QuerySet(查询集合),它是针对单个对象的操作,用于创建、更新或者删除单个模型实例。
QuerySet 适用于需要查找多个对象或进行聚合操作的场景,而 Instance 适用于单独对象的创建、修改和删除操作。
创建一个对象
Obj = Model(attr1=val1, attr2=val2),Obj.save()
更新一个对象
Obj = Model.objects.get(id=xxx),Obj.attr1 = val1,Obj.save()
删除一个对象
Obj = Model.objects.get(id=xxx),Obj.delete()
操作演示
打开shell
我们使用 shell 来熟悉 QuerySet 和 Instance 的操作
ctrl + `
打开 vscode
终端,执行进入 erp
目录,打开 shell
python manage.py shell
(ybw) PS D:\星球项目\django后端开发> cd .\erp\
(ybw) PS D:\星球项目\django后端开发\erp> python .\manage.py shell
(ybw) PS D:\星球项目\django后端开发\erp> python .\manage.py shell
Python 3.11.2 | packaged by Anaconda, Inc. | (main, Mar 27 2023, 23:35:04) [MSC v.1916 64 bit (AMD64)]
Type 'copyright', 'credits' or 'license' for more information
IPython 8.13.2 -- An enhanced Interactive Python. Type '?' for help.
In [1]:
导入 models.py 中的2个类
from apps.models import *
models.py 中有2个类
GoodsCategory 和 Goods
## 产品分类表
class GoodsCategory(Model):
"""产品分类"""
name = CharField(max_length=64, verbose_name='分类名称')
remark = CharField(max_length=64, null=True, verbose_name='备注', blank=True)
## 产品表
class Goods(Model):
"""产品"""
# 外键
category = ForeignKey(GoodsCategory, on_delete=SET_NULL, related_name='goods_set', null=True, verbose_name='产品分类',
blank=True, )
# on_delete
number = CharField(max_length=32, verbose_name='产品编号')
name = CharField(max_length=64, verbose_name='产品名称')
barcode = CharField(max_length=32, null=True, blank=True, verbose_name='条码')
spec = CharField(max_length=64, null=True, blank=True, verbose_name='规格')
shelf_life_days = IntegerField(null=True, verbose_name='保质期天数')
purchase_price = FloatField(default=0, verbose_name='采购价')
retail_price = FloatField(default=0, verbose_name='零售价')
remark = CharField(max_length=128, null=True, blank=True, verbose_name='备注')
QuerySet 和 Instance 演示
QuerySet 示例
all() :返回全部对象
In [2]: GoodsCategory.objects.all()
Out[2]: <QuerySet [<GoodsCategory: 水果>, <GoodsCategory: 动物>, <GoodsCategory: 电脑>, <GoodsCategory: 眼镜>, <GoodsCategory: 衣服>, <GoodsCategory: 皮鞋>, <GoodsCategory: 茶壶>]>
In [6]: Goods.objects.all()
Out[6]: <QuerySet [<Goods: 苹果>, <Goods: 桃子>, <Goods: 猴子>, <Goods: 大象>]>
这里分别显示了GoodsCategory
和Goods
的全部对象
values():显示更详细信息
In [4]: GoodsCategory.objects.values()
Out[4]: <QuerySet [{'id': 2, 'name': '水果', 'remark': '水果'}, {'id': 3, 'name': '动物', 'remark': '动物'}, {'id': 9, 'name': '电脑', 'remark': None}, {'id': 13, 'name': '眼镜', 'remark': None}, {'id': 14, 'name': '衣服', 'remark': '衣服'}, {'id': 15, 'name': '皮鞋', 'remark': '皮鞋'}, {'id': 16, 'name': '茶壶', 'remark': None}]>
In [7]: Goods.objects.values()
Out[7]: <QuerySet [{'id': 1, 'category_id': 2, 'number': '1', 'name': '苹果', 'barcode': None, 'spec': None, 'shelf_life_days': 10, 'purchase_price': 3.0, 'retail_price': 5.0, 'remark': None}, {'id': 2, 'category_id': 2, 'number': '2', 'name': '桃子', 'barcode': None, 'spec': None, 'shelf_life_days': 10, 'purchase_price': 4.0, 'retail_price': 6.0, 'remark': None}, {'id': 3, 'category_id': 3, 'number': '3', 'name': '猴子', 'barcode': None, 'spec': None, 'shelf_life_days': 40, 'purchase_price': 60.0, 'retail_price': 100.0, 'remark': None}, {'id': 4, 'category_id': 3, 'number': '4', 'name': '大象', 'barcode': None, 'spec': None, 'shelf_life_days': 200, 'purchase_price': 100.0, 'retail_price': 200.0, 'remark': None}]>
可以看出GoodsCategory
包含id
,name
,remark
3个特征
Goods
包含id
,category_id
,number
,name
,barcode
,spec
,shelf_life_days
,purchase_price
,retail_price
,remark
10个特征
In [16]: Goods.objects.values('number', 'name', 'retail_price')
Out[16]: <QuerySet [{'number': '1', 'name': '苹果', 'retail_price': 5.0}, {'number': '2', 'name': '桃子', 'retail_price': 6.0}, {'number': '3', 'name': '猴子', 'retail_price': 100.0}, {'number': '4', 'name': '大象', 'retail_price': 200.0}]>
只显示number
,name
,retail_price
3个特征
count():计算对象数目
In [19]: GoodsCategory.objects.all().count()
Out[19]: 7
In [20]: Goods.objects.values().count()
Out[20]: 4
In [32]: queryset = GoodsCategory.objects.all()
In [33]: queryset.count()
Out[33]: 7
可以看出GoodsCategory
包含7个对象,Goods
包含4个对象
同时QuerySet
的结果可以赋给变量,进行后续操作
filter():筛选符合条件的对象
In [5]: GoodsCategory.objects.values().filter(remark=None)
Out[5]: <QuerySet [{'id': 9, 'name': '电脑', 'remark': None}, {'id': 13, 'name': '眼镜', 'remark': None}, {'id': 16, 'name': '茶壶', 'remark': None}]>
返回remark=None
的对象
In [18]: Goods.objects.values('number', 'name', 'retail_price').filter(number__gt=2)
Out[18]: <QuerySet [{'number': '3', 'name': '猴子', 'retail_price': 100.0}, {'number': '4', 'name': '大象', 'retail_price': 200.0}]>
返回number > 2
的对象
In [23]: Goods.objects.values('number', 'name', 'retail_price').filter(number__gt=1, retail_price__lt=150)
Out[23]: <QuerySet [{'number': '2', 'name': '桃子', 'retail_price': 6.0}, {'number': '3', 'name': '猴子', 'retail_price': 100.0}]>
返回 number > 1
以及 retail_price < 150
的对象,即 filter
可以多个条件联合使用
exclude():排除符合条件的对象
In [21]: GoodsCategory.objects.values().exclude(remark=None)
Out[21]: <QuerySet [{'id': 2, 'name': '水果', 'remark': '水果'}, {'id': 3, 'name': '动物', 'remark': '动物'}, {'id': 14, 'name': '衣服', 'remark': '衣服'}, {'id': 15, 'name': '皮鞋', 'remark': '皮鞋'}]>
去除remark=None
的对象,即筛选出remark != None
的对象
update():修改数据并保存
In [25]: GoodsCategory.objects.filter(id=13).update(remark='眼镜')
Out[25]: 1
In [27]: GoodsCategory.objects.values().filter(id=13)
Out[27]: <QuerySet [{'id': 13, 'name': '眼镜', 'remark': '眼镜'}]>
将GoodsCategory
的id=13
的对象的 remark
改成眼镜
delete():删除对象
In [28]: GoodsCategory.objects.filter(name='动物').delete()
Out[28]: (1, {'apps.GoodsCategory': 1})
In [29]: GoodsCategory.objects.all()
Out[29]: <QuerySet [<GoodsCategory: 水果>, <GoodsCategory: 电脑>, <GoodsCategory: 眼镜>, <GoodsCategory: 衣服>, <GoodsCategory: 皮鞋>, <GoodsCategory: 茶壶>]>
删除name="动物"
的对象
order_by():对筛选结果排序
In [30]: Goods.objects.values('number', 'name', 'retail_price').order_by('retail_price')
Out[30]: <QuerySet [{'number': '1', 'name': '苹果', 'retail_price': 5.0}, {'number': '2', 'name': '桃子', 'retail_price': 6.0}, {'number': '3', 'name': '猴子', 'retail_price': 100.0}, {'number': '4', 'name': '大象', 'retail_price': 200.0}]>
将Goods的number
,name
,retail_price
3个特征 按照retail_price
进行升序排列
In [31]: Goods.objects.values('number', 'name', 'retail_price').order_by('-retail_price')
Out[31]: <QuerySet [{'number': '4', 'name': '大象', 'retail_price': 200.0}, {'number': '3', 'name': '猴子', 'retail_price': 100.0}, {'number': '2', 'name': '桃子', 'retail_price': 6.0}, {'number': '1', 'name': '苹果', 'retail_price': 5.0}]>
通过添加负号,将 Goods
按照降序排列
Instance示例
get():指定一个对象
In [42]: Goods.objects.get(name='苹果')
Out[42]: <Goods: 苹果>
In [43]: Goods.objects.values().get(name='苹果')
Out[43]:
{'id': 1,
'category_id': 2,
'number': '1',
'name': '苹果',
'barcode': None,
'spec': None,
'shelf_life_days': 10,
'purchase_price': 3.0,
'retail_price': 5.0,
'remark': None}
返回name="苹果"
的对象
修改一个对象
In [44]: obj = Goods.objects.get(name='苹果')
In [45]: obj.purchase_price = 4.0
In [46]: obj.retail_price = 6.0
In [47]: obj.remark = '水果'
In [48]: obj.save()
In [52]: Goods.objects.values().get(name='苹果')
Out[52]:
{'id': 1,
'category_id': 2,
'number': '1',
'name': '苹果',
'barcode': None,
'spec': None,
'shelf_life_days': 10,
'purchase_price': 4.0,
'retail_price': 6.0,
'remark': '水果'}
delete():删除一个对象
In [56]: GoodsCategory.objects.values()
Out[56]: <QuerySet [{'id': 2, 'name': '水果', 'remark': '水果'}, {'id': 9, 'name': '电脑', 'remark': None}, {'id': 13, 'name': '眼镜', 'remark': '眼镜'}, {'id': 14, 'name': '衣服', 'remark': '衣服'}, {'id': 15, 'name': '皮鞋', 'remark': '皮鞋'}, {'id': 16, 'name': '茶壶', 'remark': None}]>
In [58]: obj2 = GoodsCategory.objects.get(id=16)
In [59]: obj2
Out[59]: <GoodsCategory: 茶壶>
In [60]: obj2.delete()
Out[60]: (1, {'apps.GoodsCategory': 1})
In [61]: GoodsCategory.objects.values()
Out[61]: <QuerySet [{'id': 2, 'name': '水果', 'remark': '水果'}, {'id': 9, 'name': '电脑', 'remark': None}, {'id': 13, 'name': '眼镜', 'remark': '眼镜'}, {'id': 14, 'name': '衣服', 'remark': '衣服'}, {'id': 15, 'name': '皮鞋', 'remark': '皮鞋'}]>
删除GoodsCategory
中id=2
的对象,即name="茶壶"
的对象
最后更新于