Tortoise ORM 之增删改查

Tortoise ORM 之增删改查

查询

1. 使用 await 和 不使用 await 的区别

使用 await 查询

使用 await 查询时,得到的结果是 Model 对象,可以直接获取其属性。

objs = await UserModel.filter(uuid__in=apps_uuid)
# {VirtualAppModel} <VirtualAppModel>
print(objs[0].name)
不使用 await 查询

不使用 await 查询时,得到的是 tortoise.queryset.QuerySet 对象,无法通过循环遍历获取每一个对象的具体属性,但是支持链式查询,适合在进行分页时使用。

objs = UserModel.filter(uuid__in=apps_uuid)
# obj: <tortoise.queryset.QuerySet object at 0x00000132C4EBF160>
objs = objs.filter(name=xxx)
objs = objs.filter(xxx=xxxx)

2. 判断对象是否存在

result = await UserModel.exists(uuid=xxx)

3. 获取单条数据

user = await UserModel.get(uuid=xxx)  # <UserModel>
# 1.如果查询到多条数据,则抛出异常:tortoise.exceptions.MultipleObjectsReturned
# 2.如果没找到数据,则抛出异常:tortoise.exceptions.DoesNotExist

user = await UserModel.get_or_none(uuid=xxx)  # <UserModel> or None
# 1.如果没找到数据,返回:None
# 2.如果查询到多条数据,则抛出异常:tortoise.exceptions.MultipleObjectsReturned

4. 获取多条数据

users = await UserModel.filter(name=xxx)  # [<UserModel>]

5. 获取所有数据

users = await UserModel.all()  # [<UserModel>, <UserModel>, ...]

6. 获取第一条数据

data = await UserModel.first()  # <UserModel>

7. 仅获取模型中部分的字段

data_dict = await UserModel.first().values("name", "uuid")
# 如果查询结果是单条数据:{'name': '222224', 'uuid': '35f01c8a57aa44008c99682f0eece37a'}
# 如果查询结果是多条数据:[{'name': 'xxx', 'uuid': 'xxx'}, {'name': 'xxx', 'uuid': 'xxx'}]

data_tuple = await UserModel.first().values_list("name", "uuid")  
# 元组形式,只返回值:('222224', '35f01c8a57aa44008c99682f0eece37a')
# 多条数据:[('222224', '35f01c8a57aa44008c99682f0eece37a'), ('xxx', 'xxx')]

# 如果想获取多条数据中的某一个字段,比如 uuid,正常情况下返回:[('xxx',), ('xxx'),...]
# 但如果想要的结果为:['xxx', 'xxx', 'xxx', ...],就需要另一个参数了
uuid_list = await UserModel.filter(name__startswith='xxx').values_list("uuid", flat=True) 

# 如果想获取部分字段,但是以 object 对象形式返回
data = await UserModel.first().only("name") 
# 如果查询结果是单条数据:<UserModel>,不过这个模型对象中只有 name 属性,强行获取其他属性,则会报错
# 如果查询结果是多条数据:[<UserModel>]

8. select_related、prefetch_related

常用于关联模型查询中,减少数据库访问频次,提高查询性能,具体可以查看 Django ORM 中的示例

9. 不等于:exclude

比如查询 name 不等于 111 的用户。

data = await UserModel.exclude(name='111')

10. 数据去重

data = await UserModel.filter(name='111').distinct()

11. 统计条数

num = await UserModel.filter(name='test').count()
# 或者
queryset = UserModel.filter(name='test')
num = await queryset.count()
data = await queryset.all()

12. 聚合查询

from tortoise.functions import Count, Trim, Lower, Upper, Coalesce

await Tournament.annotate(events_count=Count('events')).filter(events_count__gte=10)
await Tournament.annotate(clean_name=Trim('name')).filter(clean_name='tournament')
await Tournament.annotate(name_upper=Upper('name')).filter(name_upper='TOURNAMENT')
await Tournament.annotate(name_lower=Lower('name')).filter(name_lower='tournament')
await Tournament.annotate(desc_clean=Coalesce('desc', '')).filter(desc_clean='')

13. 双下划线查询

根据字段值进行过滤。

关键字意义使用方法
not不等于name__not='xxx'
in范围内name__in=['xxx', 'xxx']
not_in范围外name__not_in=['xxx', 'xxx']
gte大于或等于age__gte=22
gt大于age__gt=22
lte小于等于age__lte=45
lt小于age__lt=45
range范围查询age__range=(18,45)
isnullnull 查询desc__isnull=True
not_isnull非 null 查询desc__not_isnull=True
contains包含查询name__contains="test"
icontains不区分大小写包含查询name__icontains="test"
startswith开头查询name__startswith="test"
istartswith不区分大小写开头查询name__istartswith="test"
endswith结尾查询name__endswith="test"
iendswith不区分大小写结尾查询name__iendswith="test"
iexact不区分大小写的等于name__iexact="test"
search全文检索(测试报错)name__search="test"
year年份查询created_at__year=2020
month月份查询created_at__month=7
day日查询created_at__day=24

14. JSON 类型数据查询

# 列表形式
# extra 字段值:["text", 3, {"msg": "msg2"}]
obj = await UserModel.filter(extra__contains=[{"msg": "msg2"}]).first()

# 字典形式
# extra 字段值:{"breed": "labrador", "owner": {"name": "Boby", "last": None, "other_pets": [{"name": "Fishy"}]}}
# 2.1 根据字段进行精确匹配
obj1 = await UserModel.filter(extra__filter={"breed": "labrador"}).first()
# 2.2 嵌套字典数据获取
obj2 = await UserModel.filter(extra__filter={"owner__name": "Boby"}).first()
# 2.3 获取嵌套数据中的列表数据
obj3 = await UserModel.filter(data__filter={"owner__other_pets__0__name": "Fishy"}).first()

15. Q 查询

from tortoise.expressions import Q

users = await UserModel.filter(Q(name='a') | Q(name='b'))
# 等效于:如果省略 join_type,则为 AND
users = await UserModel.filter(Q(Q(name='a'), Q(name='b'), join_type="OR"))

# ~Q:不等于
users = await UserModel.filter(~Q(name='a'))

16. F 表达式

from tortoise.expressions import F

await UserModel.filter(uuid='xxx').update(age=F('age') - 10)

创建

1. 单条数据创建

user = await UserModel.create(uuid="xxx", name="xxx")  # <UserModel>
# 或者
user = User(uuid="xxx", name="xxx")
await user.save()

2. 批量创建

bulk_data = list()
for uuid in users_uuid:
    bulk_data.append(await UserModel(uuid=uuid, name="xxx"))
await UserModel.bulk_create(bulk_data)

3. 查询或创建

如果查询得到

,则返回该对象,否则直接创建。

# 根据名称查询,查询不到,则创建一条数据:name:xxx,age: 12
user = await UserModel.get_or_create(name='xxx', defaults={'age': 12})

更新

1. 根据条件更新

# 返回更新的数目:int
num = await UserModel.filter(uuid='xxx').update(age=24)

# 或者
user = await UserModel.get(uuid='xxx')
user.age = F('age') + 10
await user.save(update_fields=['balance'])

2. 更新或创建

# 根据 name=111 查询,如果有数据,则更新 age=26,password=password;否则,创建一条数据,name='11111'、age=26、password=password
# 返回结果为元组,第一个元素为 Model 对象,第二个元素为是否新创建的数据
data, is_create = await UserModel.update_or_create(name="11111", defaults={"age": 26, "password": "password"})

删除

1. 删除全部

# 删除的条目数
num = await UserModel.all().delete()

2. 根据条件删除

# 删除的条目数
num = await UserModel.filter(uuid='xxx').delete()
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

kanbang

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值