目录
- Django基础之模型层(models.py)、ORM查询之单表查询、多表查询和跨表查询
- ORM查询
- django测试环境搭建
- 单表查询
- 应知应会13条方法
- 神奇的双下划线查询
- 多表查询
- 外键字段的增删改查
- ORM跨表查询
- 正反向的概念
- 基于对象的跨表查询-----子查询
- 基于双下划线的跨表查询-----连表查询
Django基础之模型层(models.py)、ORM查询之单表查询、多表查询和跨表查询
ORM查询
如果想查看orm语句内部真正的sql语句,有两种方式:
1.如果是queryset对象 那么可以点query直接查看该queryset的内部sql语句
2.在django项目的配置文件中 配置一下参数即可实现所有的orm在查询的时候自动打印对应的sql语句,把下面的代码加到settings配置文件中即可
LOGGING = {
'version': 1,
'disable_existing_loggers': False,
'handlers': {
'console': {
'level': 'DEBUG',
'class': 'logging.StreamHandler',
},
},
'loggers': {
'django.db.backends': {
'handlers': ['console'],
'propagate': True,
'level': 'DEBUG',
},
}
}
django测试环境搭建
拷贝manage.py文件中的四行代码到tests.py文件中,再在tests.py中写两行代码
tests.py
import os
if __name__ == "__main__":
os.environ.setdefault("DJANGO_SETTINGS_MODULE", "Books_Manage_System.settings")
import django
django.setup()
# 就可以在下面测试django任何的py文件
单表查询
应知应会13条方法
13个方法
1、all():查所有的数据,结果是Queryset对象,但是是惰性查询,要用数据的时候才去查数据显示出来,不用的话不去查
2、filter():也是惰性查询,结果也是Queryset对象,需要查询条件
3、get():查数据对象本身,不推荐使用
4、order_by():排序,默认升序,括号里的条件加负号就是降序
5、reverse():反转:前面必须是经过order_by()排序的数据才能反转
6、exclude():除满足条件的数据外的所有数据
7、values():括号里也要条件,结果也是Queryset对象,列表套字典
8、values_list():括号里也要条件,结果也是Queryset对象,列表套元组
9、count():统计数据的条数
10、distinct():去重:数据必须是完全一模一样的情况下才能去重
11、exists():判断数据是否存在,返回结果True或False,没有什么用
12、first():拿第一个
13、last():拿最后一个
只要是queryset对象就可以无限制的点queryset对象的方法
神奇的双下划线查询
# 查询价格大于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)
"""原生sql语句:模糊匹配
like
%
_
"""
# 查询书籍名字中包含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语句的时候,跟写sql语句一样,不要想着一次性写完,最好写一点查一点看一点
外键字段的增删改查
一对多字段的增删改查
增
# 方式一
models.Book.objects.create(title='三国演义', price=123.23, publish_id=1) # publish_id直接传出版社主键值
# 方式二
publish_obj = models.Book.objects.fliter(pk=2).first()
models.Book.objects.create(title='三国演义', price=123.23, publish=publish_obj) # publish直接传出版社数据对象
查
book_obj = models.Book.objects.filter(pk=1).first()
print(book_obj.publish) # 得到该书籍对应的出版社对象
print(book_obj.publish_id) # 得到该书籍对应的出版社的id
改
# 方式一
models.Book.objects.filter(pk=1).update(publish_id=3)
# 方式二
publish_obj = models.Punlish.filter(pk=2).first()
models.Book.objects.filter(pk=1).update(publish=publish_obj)
删
models.Publish.objects.filter(pk=3).delete()
# 默认是级联更新、级联删除
多对多字段的增删改查
增加关系
add()
book_obj = models.Book.objects.filter(pk=3).first()
print(book_obj.authors) # 相当于直接跳到了书籍和作者的关系表了
book_obj.authors.add(1) # 给主键为3的书籍添加主键为1的作者
book_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 = models.Book.objects.filter(pk=3).first()
book_obj.authors.set([3,])
author_obj = models.Author.objects.filter(pk=1).first()
author_obj1 = models.Author.objects.filter(pk=2).first()
book_obj.authors.set(author_obj) # 可以直接添加作者对象
book_obj.authors.set(author_obj,author_obj1)
# 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跨表查询
1、子查询
2、连表查询
正反向的概念
书籍对象查出版社,外键字段在书籍,正向查询(有外键字段的来查就是正向)
出版社查书籍,外键字段在书籍,反向查询(有外键字段的被查就是反向)
基于对象的跨表查询-----子查询
正向查询按字段,当该字段所对应的数据有多个的时候,需要加.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();当查询的结果有且只有一个的情况下,不需要加任何东西,直接表名小写即可
# 反向查询
# 4、查询出版社是东方出版社出版过的书籍
publish_obj = models.Publish.objects.filter(name='东方出版社').first()
print(publish_obj.book_set) # 结果是app01.Book.None
print(publish_obj.book_set.all()) # 加.all()就能拿到该出版社出版的所有书
# 5、查询作者是jason写过的所有书
author_obj = models.Author.objects.filter(name='jason').first()
print(author_obj.book_set.all())
# 6、查询手机号是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)