DjangoORM数据操作
配置测试脚本
from django.test import TestCase
import os
if __name__ == "__main__":
os.environ.setdefault("DJANGO_SETTINGS_MODULE", "day53.settings")
import django
django.setup()
创建数据
我们现在models文件中创建好Book,Publish,Author,AuthorDetail这四张表
create方法
models.AuthorDetail.objects.create(phone='110', email='[email protected]')models.AuthorDetail.objects.create(phone='120', email='[email protected]')models.Author.objects.create(name='冯*内古特', age=80, author_detail_id=1)models.Author.objects.create(name='菲茨杰拉德', age=44, author_detail_id=2)models.Book.objects.create(title='了不起的盖茨比', price=28.8, book_type='文学', publish_id=2)
修改数据
pk会自动帮你查找到当前表的主键字段,所以后期我们都是用pk来指代主键字段
filter查询出来的结果是一个Queryset对象
只要是queryset对象就可以无限制的调用queryset的方法
res = models.Books.objects.filter(pk=1).filter().filter().filter().filter()
只要是queryset对象就可以点query查看当前结果内部对应的sql语句
res.query
方式一
models.Book.objects.filter(pk=2).update(price=29.8)
方式二(不推荐使用)
# 利用对象的修改 内部其实是重头到位将数据的所有字段都重新写一遍
book_obj = models.Books.objects.get(pk=1)
book_obj.price = 28.8
book_obj.save()
get和filter的区别
filter获取到的是一个queryset对象,类似于一个列表
get获取到的直接就是数据对象本身
当条件不存在的情况下
filter不报错直接返回一个空 推荐使用filter方法
get直接报错 所以不推荐使用get方法
删除数据
- 利用queryset方法 delete()
models.Book.objects.filter(pk=3).delete()
- 对象方法
book_obj = models.Book.objects.get(pk=3)
book_obj.delete()
查询数据
13个方法
方法 | 作用 | 示例 |
---|---|---|
all() | 查询所有 | models.Book.objects.all() |
filter() | 筛选 | models.Book.objects.filter(pk=1) |
get() | 筛选(不存在会报错) | models.Book.objects.get(pk=1) |
first() | 取queryset第一个数据对象 | models.Book.objects.filter(publish_id=2).first() |
last() | 取queryset最后一个数据对象 | models.Book.objects.filter(publish_id=2).last() |
count() | 统计数据个数 | models.Book.objects.count() |
values() | 获取指定字段的值(列表套字典) | models.Book.objects.values('title', 'price') |
values_list() | 获取指定字段的值(列表套元组) | models.Book.objects.values_list('title', 'price') |
order_by() | 按照指定的字段排序 | models.Book.objects.all().order_by('price') 字段前面加符号表示降序 |
reverse() | 颠倒顺序(前提是已经排好序) | models.Book.objects.all().order_by('price').reverse() |
exclude() | 排除指定的字段的值 | models.Book.objects.all().excl(title='2081') |
exists() | 判断查询结果是否有值 | models.Book.objects.filter(pk=1).exists() |
diistinct() | 对查询结果进行去重 | models.Book.objects.values('title', 'price').distinct() |
双下划线
# 查询价格大于30的书籍
res = models.Book.objects.filter(price__gt=30)
print(res)
# 查询价格小于30的书籍
res = models.Book.objects.filter(price__lt=30)
print(res)
# 查询价格大于等于30的书籍
# 对数字精确度不敏感?
res = models.Book.objects.filter(price__gte=30)
print(res)
# 查询价格小于等于30的书籍
res = models.Book.objects.filter(price__lte=30)
print(res)
# 查询价格是20或者30或者50的书籍
res = models.Book.objects.filter(price__in=[20, 30, 50])
print(res)
# 查询价格在20到50之间的书籍(顾头又顾尾)
res = models.Book.objects.filter(price__range=(20, 50))
print(res)
# 查询注册日期是2019的用户
res = models.User.objects.filter(register_time__year='2019')
print(res)
# 查询注册日期是11月份的用户
res = models.User.objects.filter(register_time__month='11')
# 模糊查询
# 查询书籍是与霍开头的书
res = models.Book.objects.filter(title__startswith='霍')
print(res)
# 查询书籍是以情结尾的书
res = models.Book.objects.filter(title__endswith='情')
print(res)
# 查询书籍中含有p字母的书
res = models.Book.objects.filter(title__contains='p') # 默认区分大小写
res = model.Book.objects.filter(title__icontains='P') # 忽略大小写
print(res)
一对多字段数据的增删改查
增
# 方式一
models.Book.objects.create(title='了不起的盖茨比', price=28.8, book_type='文学', publish_id=2)
# 方式二
publish_obj = models.Publish.objects.filter(pk=2).first()
models.Book.objects.create(title='了不起的盖茨比', price=28.8, book_type='文学', publish=publish_obj)
改
# 方式一
models.Book.objects.filter(pk=2).update(publish_id=1)
# 方式二
publish_obj = models.Publish.objects.filter(pk=1).first()
models.Book.objects.filter(pk=1).update(publish=publish_obj)
删
models.Publish.objects.filter(pk=1).delete() # 默认就是级联删除 级联更新
多对多字段数据的增删改查
增
# 方式一
book_obj = models.Book.objects.filter(pk=2).first()
book_obj.author.add(1,3) # book_obj.author已经跨到第三张表了
# 方式二
book_obj = models.Book.objects.filter(pk=2).first()
author_obj = models.Book.objects.filter(pk=1).first()
author_obj1 = models.Book.objects.filter(pk=3).first()
book_obj.author.add(author_obj, author_obj1)
add方法能够朝第三张关系表添加数据
即支持传数字
add(1, 3)
也支持传对象
add(author_obj, author_obj1)
并且可以多个
改
# 方式一
book_obj = models.Book.objects.filter(pk=2).first()
book_obj.author.set([4,5])
# 方式二
book_obj = models.Book.objects.filter(pk=2).first()
author_obj = models.Book.objects.filter(pk=4).first()
author_obj1 = models.Book.objects.filter(pk=5).first()
book_obj.author.set((author_obj, author_obj1))
set修改多对多关系表中的数据
既可以传数字也可以传对象
但是需要注意的是括号内必须是迭代对象
都支持多个
删
# 方式一
book_obj = models.Book.objects.filter(pk=2).first()
book_obj.author.remove(1,3) # book_obj.author已经跨到第三张表了
# 方式二
book_obj = models.Book.objects.filter(pk=2).first()
author_obj = models.Book.objects.filter(pk=1).first()
author_obj1 = models.Book.objects.filter(pk=3).first()
book_obj.author.remove(author_obj, author_obj1)
清空
book_obj = models.Book.objects.filter(pk=2).first()
book_obj.author.clear()
clear清空书籍相关的所有记录,括号内不需要传递参数
跨表查询
正反向查询
关系字段在哪张表里,由这张表查另一张表就是正向,否则就是反向
基于对象的跨表查询
- 查询书籍主键为2的出版社名称
book_obj = models.Book.objects.filter(pk=2).first()
print(book_obj.publish.name)
- 查询书籍主键为4的作者姓名
book_obj = models.Book.objects.filter(pk=2).first()
print(book_obj.author.all().values('name'))
- 查询作者是jason的手机号码
author_obj = models.Author.objects.filter().first()
print(author_obj.author_detail.phone)
注意
什么时候要加all
当正向查询点击外键字段数据有多个的情况下,需要.all()
app01.Author.None 一旦看到该结果,只需要加.all()即可
反向查询
- 查询出版社是南方出版社出版过的书籍
publish_obj = models.Publish.objects.filter(name='南方出版社').first()
print(publish_obj.book_set.all())
- 查询作者是jason写的书籍
author_obj = models.Author.objects.filter(name='jason').first()
print(author_obj.book_set.all())
- 查询手机是120的作者姓名
author_detail_obj = models.AuthorDetail.objects.filter(phone='120').first()
author_detail_obj.author_set.name
基于双下划线的跨表查询
- 查询书籍pk为2的出版社名称
# 正向
res = models.Book.objects.filter(pk=2).values('publish__name')
print(res)
# 反向
res = models.Publish.objects.filter(book__pk=2).values('name')
print(res)
- 查询书籍pk为2的作者姓名和邮箱
# 正向
res = models.Book.objects.filter(pk=2).values('author__name', 'author__email')
print(res)
# 反向
res = models.Author.objects.filter(book__pk=2).values('name', 'email')
print(res)
- 查询作者是egon的家庭住址
# 正向
res = models.Author.objects.filter(name='egon').values('author_detail__addr')
print(res)
# 反向
res = models.AuthorDetail.filter(author__name='egon').values('addr')
print(res)
- 查询出版社是东方出版社出版过的书的名字
# 反向
res = models.Publish.objects.filter(name='东方出版社').values('book__title')
print(res)
# 正向
res = models.Book.objects.filter(publish__name='东方出版社').values('title')
print(res)
- 查询书籍pk是2的作者的手机号
# 正向
res = models.Book.objects.filter(pk=2).values('author__author_detail__phone')
print(res)
# 反向
res = models.Author.objects.filter(book__pk=2).values('author_detail__phone')
print(res)
res = models.AuthorDetail.objects.filter(author__book__pk=2).values('phone')
print(res)