Django基础之模型层(models.py)、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)

猜你喜欢

转载自www.cnblogs.com/zhuangyl23/p/11735754.html