Django之ORM相关操作
目录ORM执行SQL语句
有时因为ORM的操作效率偏低,可以自己编写SQL提升效率。
在Django中使用原生Sql主要有以下几种方式:
1.extra:结果集修改器,一种提供额外查询参数的机制
2.raw:执行原始sql并返回模型实例
3.直接执行自定义Sql
# 这种方式完全不依赖model,前两种还是要依赖于model
代码示例:
# extra:
1:Book.objects.filter(publisher__name='北方出版社').extra(where=['price>50'])
Book.objects.filter(publisher__name='北方出版社',price__gt=50)
2:Book.objects.extra(select={'count':'select count(*) from hello_Book'})
# raw:
Book.objects.raw('select * from hello_Book')
自定义sql:
Book.objects.raw("insert into hello_author(name) values('测试')")
rawQuerySet为惰性查询,只有在使用时生会真正执行
# 执行自定义sql:
from django.db import connection
cursor=connection.cursor()
#插入操作
cursor.execute("insert into hello_author(name) values('郭敬明')")
#更新操作
cursor.execute('update hello_author set name='abc' where name='bcd'')
#删除操作
cursor.execute('delete from hello_author where name='abc'')
#查询操作
cursor.execute('select * from hello_author')
raw=cursor.fetchone() #返回结果行游标直读向前,读取一条
cursor.fetchall() #读取所有
神奇的双下划线查询
# 查询价格大于200的书籍
res = models.Book.objects.filter(price__gt=200)
print(res)
# 查询价格小于200的书籍
res = models.Book.objects.filter(price__lt=200)
print(res)
# 查询价格大于等于200.22的书籍
res = models.Book.objects.filter(price__gte=200.22)
print(res)
# 查询价格小于等于200.22的书籍
res = models.Book.objects.filter(price__lte=200.22)
print(res)
# 查询价格要么是200,要么是300,要么是666.66
res = models.Book.objects.filter(price__in=[200,300,666.66])
# 都包含
print(res)
# 查询价格在200到800之间的
res = models.Book.objects.filter(price__range=(200,800))
# 顾头不顾尾
print(res)
# 查询书籍名字中包含p的
res = models.Book.objects.filter(title__contains='p')
# 区分大小写,仅仅只能拿小写p
res1 = models.Book.objects.filter(title__icontains='p')
# 忽略大小写
print(res)
print(res1)
# 查询书籍是以三开头的
res = models.Book.objects.filter(title__startswith='三')
# 查询以三开头的
res1 = models.Book.objects.filter(title__endswith='P')
# 查询以P结尾的,区分大小写
print(res)
print(res1)
# 查询出版日期是2019年的书籍(******)
res = models.Book.objects.filter(publish_date__year='2019')
print(res)
# 查询出版日期是10月的书籍
res = models.Book.objects.filter(publish_date__month='10')
print(res)
ORM外键字段的创建
外键名 = models.ForeignKey("类名",to_field="关联字段",default=默认值,on_delete=models.CASCADE,)
#关联字段必须是唯一的,这个to_field不加也可以,默认用的就是主键
1.django orm创建表关系
图书表
出版社表
作者表
作者详情表
2.关系判断
书与出版社
一本书不能对应多个出版社
一个出版社可以对应多本书
# 一对多关系.书是多,出版社是一.
ForeignKey
'''django orm外键字段针对一对多关系也是建在多的一方 '''
书与作者
一本书可以对应多个作者
一个作者可以对应多本书
# 多对多关系
ManyToManyField
'''django orm外键字段针对多对多关系 可以不用自己创建第三张表'''
作者与作者详情
一个作者不能对应多个作者详情
一个作者详情不能对个多个作者
# 一对一关系
OneToOneField
'''django orm外键字段针对一对一关系 建在查询频率较高的表中'''
"""
ManyToManyField不会在表中创建实际的字段,而是告诉django orm自动创建第三张关系表
ForeignKey、OneToOneField会在字段的后面自动添加_id后缀,如果你在定义模型类的时候自己添加了该后缀,那么迁移的时候还会再次添加_id后缀。所以不要自己加_id后缀。
"""
外键字段相关操作
# 一对多,插入数据可以直接填写表中的实际字段
models.Book.objects.create(title='三国演义', price=888.88, publish_id=1)
models.Book.objects.create(title='人性的弱点', price=777.55, publish_id=1)
# 一对多 插入数据也可以填写表中的类中字段名
publish_obj = models.Publish.objects.filter(pk=1).first()
models.Book.objects.create(title='水浒传', price=555.66, publish=publish_obj)
'''一对一与一对多一致,既可以传数字也可以传对象。'''
# 针对多对多关系绑定
增加字段关系add()
book_obj = models.Book.objects.filter(pk=1).first()
bool_obj.authors.add(1)# 在第三张关系表中给当前书籍绑定作者
bool_obj.authors.add(2, 3) # 给主键为3的书籍添加主键为2和3的作者
author_obj = models.Author.objects.filter(pk=1).first()
author_obj1 = models.Author.objects.filter(pk=2).first()
book_obj.authors.add(author_obj) # 可以直接添加作者对象
book_obj.authors.add(author_obj,author_obj1)
"add()括号内既可以直接传数字也可以传数据对象,并且支持传多个"
# 修改关系set()
book_obj.author.set([2, ])
book_obj.author.set([2, 3])
book_obj.author.set([author_obj1, ])
book_obj.author.set([author_obj1, author_obj2])
"set()括号内必须是可迭代对象"
# 删除对象remove()
book_obj = models.Book.objects.filter(pk=3).first()
book_obj.authors.remove(2)
book_obj.authors.remove(1,2)
author_obj = models.Author.objects.filter(pk=1).first()
author_obj1 = models.Author.objects.filter(pk=2).first()
book_obj.authors.remove(author_obj) # 可以直接传作者对象
book_obj.authors.remove(author_obj,author_obj1)
"remove()括号内既可以直接传数字也可以传数据对象,并且支持传多个"
# 清空关系clear()
book_obj = models.Book.objects.filter(pk=3).first()
book_obj.authors.clear()
"clear()括号内不需要传任何参数,直接清空当前主键为3的书籍对象的所有记录"
ORM跨表查询
"""
复习MySQL跨表查询的思路
子查询:
分步操作:将一条SQL语句用括号括起来,当作另外一条SQL的条件
连表操作:
先整合多张表之后,基于单表查询
inner join 内连接
left join 左连接
right join 右连接
"""
# 正反向的概念
正向查询(有外键字段的来查就是正向)
eg:
书籍对象查出版社,外键字段在书籍
反向查询(有外键字段的被查就是反向)
eg:
出版社查书籍,外键字段在书籍
ps:正反向的核心就看外键字段在不在当前数据所在的表中
# ORM跨表查询口诀:
正向查询按外键字段 反向查询按表名小写
基于对象的跨表查询
"正向查询按字段,当该字段所对应的数据有多个的时候,需要加.all(),否则点外键字段直接就能够拿到数据对象。"
# 1、查询书籍是python入门的出版社名称
book_obj = models.Book.objects.filter(title='python入门').first()
# 正向查询按字段
print(book_obj.publish.name)
print(book_obj.publish.addr)
# 2、查询主键是6的书籍的作者姓名
book_obj = models.Book.objects.filter(pk=6).first()
print(book_obj.authors) # 结果是app01.Author.None
print(book_obj.authors.all()) # 结果是这本书的所有作者的Queryset对象
# 3、查询作者是jason的手机号
author_obj = models.Author.objects.filter(name='jason').first()
print(author_obj.author_detail.phone) # 正向查询按字段
print(author_obj.author_detail.addr)
"反向查询按表名小写,当查询的结果可以是多个的情况下需要在表名小写后面加_set.all();当查询的结果有且只有一个的情况下,不需要加任何东西,直接表名小写即可。"
# 1、查询出版社是北方出版社出版过的书籍
publish_obj = models.Publish.objects.filter(name='北方出版社').first()
print(publish_obj.book_set) # 结果是app01.Book.None
print(publish_obj.book_set.all()) # 加.all()就能拿到该出版社出版的所有书
# 2、查询作者是jason写过的所有书
author_obj = models.Author.objects.filter(name='jason').first()
print(author_obj.book_set.all())
# 3、查询手机号是110的作者
author_detail_obj = models.AuthorDetail.objects.filter(phone=110).first()
print(author_detail_obj.author) # 这个拿到作者对象
print(author_detail_obj.author.name)
print(author_detail_obj.author.age)
基于上下划线的跨表查询
# 1、查询书籍是python入门的出版社名称
res = models.Book.objects.filter(title='python入门').values('publish__name')
print(res) # 正向查询按字段publish查
#2、查询作者是jason的手机号码
# 正向
res1 = models.Author.objects.filter(name='jason').values('author_detail__phone')
print(res1) # 正向查询按字段查
# 反向
res = models.AuthorDetail.objects.filter(author__name='jason').values('phone')
# 3、查询手机号是120的作者姓名
# 正向
res2 = models.AuthorDetail.objects.filter(phone=120).values('author__name') # 反向查询按表名小写查
print(res2)
# 反向
res3 =models.Author.objects.filter(author_detail__phone=120).values('name')
# 4、查询出版社是东方出版社出版的书籍名称和出版社地址
res = models.Publish.objects.filter(name='东方出版社').values('book__title','addr') # 也是反向查询按表名小写
# 5、查询书籍是python入门的作者的手机号(连续跨表查询)
res = models.Book.objects.filter(title='python入门').values('authors__author_detail__phone')
print(res)
进阶操作
# 1.查询主键为1的书籍对应的出版社名称
res = models.Publish.objects.filter(book__pk=1).values('name')
print(res)
# 2.查询主键为4的书籍对应的作者姓名
res=models.Author.objects.filter(book__pk=4).values('name','book__title')
print(res)
# 3.查询jason的电话号码
res = models.AuthorDetail.objects.filter(author__name='jason').values('phone')
print(res)
# 4.查询北方出版社出版过的书籍名称和价格
res = models.Book.objects.filter(publish__name='北方出版社').values('title','price')
print(res)
# 5.查询jason写过的书籍名称
res = models.Book.objects.filter(authors__name='jason').values('title')
print(res)
# 6.查询电话号码是110的作者姓名
res = models.Author.objects.filter(author_detail__phone=110).values('name')
print(res)
# 补充
1.查询主键为4的书籍对应的作者的电话号码
res = models.Book.objects.filter(pk=4).values('authors__author_detail__phone')
print(res)
res = models.AuthorDetail.objects.filter(author__book__pk=4).values('phone')
print(res)
res = models.Author.objects.filter(book__pk=4).values('author_detail__phone')
print(res)
标签:obj,objects,author,models,res,Django,filter,ORM,操作
From: https://www.cnblogs.com/zhiliaowang/p/16986160.html