ORM数据库查询操作(单表,多表)(day64)

脚本测试:想在django中对某一个py文件进行测试,可以直接在项目文件中写一个测试脚本文件,一般在test.py文件中,也可以自己创建一个py文件

#先在manage.py文件中将前四行代码拷贝过来,并且加上两句代码,然后书写自己要测试的代码,运行。本章节在这里进行ORM操作
import os
import sys
if __name__ == "__main__":
    os.environ.setdefault("DJANGO_SETTINGS_MODULE", "day64.settings")

    import django
    django.setup()

单表操作

#
#方式1
res=models.User.objects.create(name='jack',age=18,register_time='2002-10-16')
#拿到一个用户空对象,在空对象里面对字段名进行添加
方式2
#import datetime
#ctime = datetime.datetime.now()
user_obj = models.User(name='Tom',age=20,register_time=ctime)
user_obj.save()
#相当于直接对类属性进行修改,注意修改完之后需要进行.save操作,将结果进行保存

#
#方式1
res = models.User.objects.filter(pk=2).delete()#批量删除
"""
pk就表示主键,任意一个表的主键都能用pk指代,自己设置的主键字段名可能会被修改,使用pk防止出错
"""
方式2
user_obj = models.User.objects.filter(pk=1).first()
user_obj.delete()#针对性删除

#
#方式1:使用了update方法进行修改
models.User.objects.filter(pk=4).update(name='egonDSB')
#方式2:也相当于是对类属性进行修改吧,所以需要保存
# user_obj = models.User.objects.get(pk=4)#找不到就报错,不建议使用user_obj = models.User.objects.filter(pk=6)#不报错,推荐使用user_obj.name = 'egonPPP'user_obj.save()#一定要记得.save()保存

必知必会13条:ORM操作中很重要的13条基本语法,常用,其他的语法可以用到、看到的时候自己积累

# 1.all()  查询所有数据

    # 2.filter()     带有过滤条件的查询
    # 3.get()        直接拿数据对象 但是条件不存在直接报错
    # 4.first()      拿queryset里面第一个元素
res = models.User.objects.all().first()
print(res)
    # 5.last()
res = models.User.objects.all().last()
print(res)

    # 6.values()  可以指定获取的数据字段  select name,age from ...     列表套字典
res = models.User.objects.values('name','age')  # <QuerySet [{'name': 'jason', 'age': 18}, {'name': 'egonPPP', 'age': 84}]>
print(res)
    # 7.values_list()  列表套元祖
res = models.User.objects.values_list('name','age')  # <QuerySet [('jason', 18), ('egonPPP', 84)]>
print(res)
    # """
    #  查看内部封装的sql语句
    #  上述查看sql语句的方式  只能用于queryset对象
    #  只有queryset对象才能够点击query查看内部的sql语句
    #
    # """
    # 8.distinct()  去重
res = models.User.objects.values('name','age').distinct()
print(res)
    """
    去重一定要是一模一样的数据,如果带有主键那么肯定不一样,你在往后的查询中一定不要忽略主键
    """
    # 9.order_by()
res = models.User.objects.order_by('age')  # 默认升序
res = models.User.objects.order_by('-age')  # 降序
print(res)
    # 10.reverse()  反转的前提是 数据已经排过序了  order_by()
res = models.User.objects.all()
res1 = models.User.objects.order_by('age').reverse()
print(res,res1)

    # 11.count()  统计当前数据的个数
res = models.User.objects.count()
print(res)
    # 12.exclude()  排除在外
res = models.User.objects.exclude(name='jason')
print(res)

    # 13.exists()  基本用不到因为数据本身就自带布尔值  返回的是布尔值
res = models.User.objects.filter(pk=10).exists()
 print(res)

在第七条中讲到了有关查看ORM内部sql语句的使用,那么在这里说明一下:

# 方式1
res = models.User.objects.values_list('name','age')  # <QuerySet [('jason', 18), ('egonPPP', 84)]>
print(res.query)
queryset对象才能够点击query查看内部的sql语句

# 方式2:所有的sql语句都能查看
# 去配置文件中配置一下即可
LOGGING = {
    'version': 1,
    'disable_existing_loggers': False,
    'handlers': {
        'console':{
            'level':'DEBUG',
            'class':'logging.StreamHandler',
        },
    },
    'loggers': {
        'django.db.backends': {
            'handlers': ['console'],
            'propagate': True,
            'level':'DEBUG',
        },
    }
}
#那么所有的数据库查询语句都能通过.query的方式来找到对应的sql语法

神奇的双下划线查询(在查询中使用,使用方式:字段名__条件)

#1.查询年龄大于20岁的数据
res = models.User.objects.filter(age__gt=20)#grater than
print(res)

#2.询年龄小于20岁的数据
res = models.User.objects.filter(age__lt=20)#lower than
print(res)

#大于等于  小于等于
#在gt或者lt后面加上e(equal)
lte  gte
#年龄是18 20 或者25
res = models.User.objects.filter(age__in=[18,20,25])
print(res)

#年龄在18到30岁之间  首尾都包括
res = models.User.objects.filter(age__range = [18,30])
print(res)

#查询出名字里面含有s的数据  模糊查询(区分大小写)
res = models.User.objects.filter(name__contains='s')
print(res)
#在contains前面加上一个i(ignore),不区分大小写

#以什么什么开头  以什么什么结尾
res = models.User.objects.filter(name__startswith='j')
es1 = models.User.objects.filter(name__endswith='j')
print(res,res1)

在讲多表查询之前,先讲一个概念:正向与反向查询,理解了这个之后再去理解多表查询会好很多

正向查询:通过外键字段所在表去查对应外键指向表(ps:外键一般设置在多的一方)

反向查询:通过外键字段所指向的表去查外键字段所在表

一对一、一对多、多对多表的正反向查询均是如此

 

一对多外键的增删改查

#增(Book表中含有一个publish外键字段关联Publish表)
#方式1:直接写对应表中的字段,外键字段需要加_id(查看数据库Book表中所录入的字段明)。
models.Book.objects.create(title='python',price=899.23,publish_id=1)
#方式2:虚拟字段+对象
publish_obj = models.Publish.objects.filter(pk=2).first()
models.Book.object.filter(title='java',price=123.34,publish=publish_obj)

#
models.Publish.objects.filter(pk=1).delete()  # 级联删除

#
#方式一:虚拟字段+对象
通过Book表中录入字段名publish_id
models.Book.objects.filter(pk=1).update(publish_id=2)
方式2:publish_obj = models.Publish.objects.filter(pk=1).first()#先查到需要修改的字段的对象
models.Book.objects.filter(pk=1).update(publish=publish_obj)

多对多外键增删改查

#增
#
如何给书籍添加作者:(书籍与作者关系是多对多) #方式1:通过id添加 #首先找到要添加作者的书籍对象 book_obj = models.Book.objects.filter(pk=1).first() #将该书籍对象通过Book表中的author字段关联到作者表中 book_obj.author book_obj.authors.add(1)#添加一个id值为1的作者 book_obj.authors.add(2,3)#同时添加id值为2,3的作者
#如果add之后的id值不存在就会报错
#方式2:通过对象添加 #首先找到要添加作者的书籍对象 book_obj = models.Book.objects.filter(pk=1).first() #找到给书籍添加作者的作者对象author_obj1 = models.Author.objects.filter(pk=2).first() author_obj2 = models.Author.objects.filter(pk=3).first() #通过对象的方法给书籍加上作者信息book_obj.authors.add(author_obj) book_obj.authors.add(author_obj1,author_obj2)
#
方式1:#通过id值删除
book_obj.authors.remove(2)
book_obj.authors.remove(1,3)
#删除的是author表中对应的作者的id值,如果没有的话也不报错
方式2:通过对象删除
author_obj = models.Author.objects.filter(pk=2).first()
author_obj1 = models.Author.objects.filter(pk=3).first()
#
方式1:通过id值或者主键值
book_obj.authors.set([1,2])  # 括号内必须给一个可迭代对象
book_obj.authors.set([3])  # 括号内必须给一个可迭代对象

方式2:通过对象
author_obj = models.Author.objects.filter(pk=2).first()
author_obj1 = models.Author.objects.filter(pk=3).first()
book_obj.authors.set([author_obj,author_obj1])  # 括号内必须给一个可迭代对象

"""
set
括号内必须传一个可迭代对象,该对象内既可以数字也可以对象 并且都支持多个
"""

# 清空
    # 在第三张关系表中清空某个书籍与作者的绑定关系
    book_obj.authors.clear()
    """
    clear
        括号内不要加任何参数
    
    """

多表查询:

先记住两句口诀:

正向查询按字段
反向查询按表名小写(可能会加_set等)  很重要!请记住

子查询(基于对象的跨表查询)

1.查询书籍主键为1的出版社
#找到主键为1的书籍对象
book_obj = models.Book.objects.filter(pk=1).first()
#直接查询该书籍对象的出版社(Book表下面的publish字段含有外键,所以是正向查询)
book_obj.publish
print(res)# print(res.name)# print(res.addr)

2.查询书籍主键为2的作者
#找到主键为1的书籍对象
book_obj = models.Book.objects.filter(pk=2).first()
#查找作者(Book表下面有的author字段含有外键,所以是正向查询)
res = book_obj.authors.all()#是一个QuerySet集合
print(res)

3.查询作者新新子的电话号码
#查找出作者为新新子的作者对象
author_obj = models.Author.objects.filter(name='新新子').first()
#找出该作者对象的所有详细信息
res = author_obj.author_detail
#点出需要查找的详细信息
print(res.phone)
print(res.addr)

正向什么时候需要加.all()?当你的结果可能有多个的时候就需要加.all()
如果是一个则直接拿到该数据对象
book_obj.publish
book_obj.authors.all()
author_obj.author_detail

4.查询出版社是东方出版社出版的书
#先找出东方出版社
publish_obj = models.Publish.objects.filter(name='东方出版社').first()
#再找出东方出版社出版的所有的书(出版社于书存在外键关系,但是外键字段再书籍表中,所以是反向查询)
res = publish_obj.book_set.all()
print(res)

5.查询作者是新新子写过的书
#先将作者新新子对象找出
author_obj = models.Author.objects.filter(name='新新子').first()
#然后找出该作者写的所有的书(作者表跟书籍表有外键关系,但是外间字段在书籍中,所以是反向查询)
res = author_obj.book_set.all()
print(res)

6.查询手机号是110的作者姓名
#先找出手机号码为110的作者详细信息对象
author_detail_obj = models.AuthorDetail.objects.filter(phone=110).first()
#查找该详细信息的作者姓名(同样作者详细信息与作者表有外间关系。但是外键字段在作者表中,故也是反向查询)
res = author_detail_obj.author
print(res.name)

"""
基于对象查询时:
反向查询的时候,当你的查询结果可以有多个的时候 就必须加_set.all()
当你的结果只有一个的时候,不需要加_set.all(),直接就是表明小写
自己总结出 自己方便记忆的即可 每个人都可以不一样
"""

联表查询(基于双下划线的跨表查询)

1.查询新新子的手机号和作者姓名
#方式1:先拿出姓名为新新子的作者对象,通过这个对象去找他的手机号。由于作者表中有一个作者详细信息的外键字段,所以直接结合前面所说的正向查询通过字段查,再通过__跨到详细信息表中去查手机号
res=models.Author.objects.filter(name='新新子').values('author_detail__phone','name')
print(res)

#方式2: 先拿到作者为新新子的所有详细信息,再找出需要的信息。由于是先从详细信息表中找作者信息,属于反向查询,按照口诀:反向查询按表明小写所以是:author__name='新新子',同过__跨到作者表中去找name
 res = models.AuthorDetail.objects.filter(author__name='新新子') # 拿作者姓名是新新子的作者详情 res=models.AuthorDetail.objects.filter(author__name='新新子').values('phone','author__name') print(res)
2.查询书籍主键为1的出版社名称和书的名称
#正向:直接找主键为1的书籍,由于书籍中含有出版社主键,要找出版社的名称,书籍中没有出版社名称,所以要通过__来跨表,跨到Publish中去查找name res
=models.Book.objects.filter(pk=1).values('title','publish__name') print(res) # 反向:先在Publish中找,Publish中没有书籍的有关信息,所以要在Publish中跨到书籍中去找,外键在Book中,所以是反向查找,通过表明小写关联,再通过__跨表过去,找title也是一样 res=models.Publish.objects.filter(book__id=1).values('name','book__title') print(res)
3.查询书籍主键为1的作者姓名
res = models.Book.objects.filter(pk=1).values('author__name')
print(res)
# 反向
res = models.Author.objects.filter(book__id=1).values('name')
print(res)
4.查询书籍主键是1的作者的手机号
# book author authordetail 一共有三张表,上来直接找出主键为1的书籍,然后根据要求,先去找作者。从书中找作者,正向,所以直接通过author字段,然后__跨到作者表中,然后从作者表中跨表寻找作者的手机号。作者表查到作者详情表正向,所以是通过作者表中的
#author_detail来关联,再通过__跨到作者详情表中寻找phone。所以一工进行了两次跨表
res=models.Book.objects.filter(pk=1).values('author__author_detail__phone') print(res)


联表查询(基于双下划线的跨表查询)总结:先看通过正向查还是反相查,根据口诀来寻找跨表的关联对象,正向通过字段关联,反向通过表名小写关联。然后通过__表示跨表,跨到需要查找的那张表中去寻找需要的字段信息。你只要掌握了正反向的概念以及双下划线,就能无限制的跨表查询。

 

posted @ 2020-10-16 23:47  方方的鱼  阅读(259)  评论(1编辑  收藏  举报