双下划线查询方法
比较运算
# 关键字:
大于: __gt
小于: __lt
大于等于: __gte
小于等于: __lte
# 举例:
res = models.User.objects.filter(age__gt=18)
print(res) # 年龄大于18
res1 = models.User.objects.filter(age__lt=18)
print(res) # 年龄小于18
res2 = models.User.objects.filter(age__gte=18)
print(res2) # 年龄大于等于18
res3 = models.User.objects.filter(age__lte=18)
print(res3) # 年龄小于等于18
在某一数据集内:
# 关键字:__in=['数据集']
# 举例:
res = models.User.objects.filter(age__in=[10,20,30,40])
print(res)
在某一范围内:
# 关键字:__range=[]
# 举例:
res = models.User.objects.filter(age__range=[19,40]) # 包含19和40
print(res)
模糊查询:
# 关键字:__contain='' 区分大小写
__icontain='' 不区分大小写
# 举例:
查询姓名中包含字母k的用户
res = models.User.objects.filter(name__contains='k')
print(res)
res1 = models.User.objects.filter(name__icontains='k')
print(res1)
以什么开头/结尾:
# 关键字:__startwith='' 以什么开头
__endswith='' 以什么结尾
__istartwith='' 不区分大小写
__iendswith='' 不区分大小写
# 举例:
models.User.objects.filter(name_ _startswith="n" )
models.User.objects.filter(name_ _endswith="n" )
按照日期查询:
# 关键字:
__month='1' # 按照月份取
__year='2020' # 按照年份
__day='29' # 按照天筛选
# 举例:
res = models.User.objects.filter(register_time__month='01')
print(res)
res1= models.User.objects.filter(register_time__day='02')
print(res1)
res3 = models.User.objects.filter(register_time__year='2022')
print(res3)
res4 = models.User.objects.filter(register_time__year='2022',register_time__month='02')
print(res4)
ORM创建外键
以书籍,出版社,作者,作者信息这4张表为例
书籍和出版社的关系:
一本书籍只能由一个出版社出版,一个出版社可以出版多本书。
关系为:一对多(ForeignKey),书籍是多所以外键创建在书籍表中。
书籍和作者的关系:
一本书可以由多个作者创作,一个作者同样也可以创作多本书。
关系为:多对多(ManyToManyField),需要创建第三张表来表示关系
作者和作者信息的关系:
一条信息对应一个作者,一个作者对应一条信息。
关系为:一对一(OneToOneField),外键应创建在查询频率较高的表中。
一对多外键关系
"""在orm中 外键字段建在多的一方"""
多对多外键关系
"""在orm中 可以直接写在查询频率较高的表中(自动创建第三张表)"""
一对一外键关系
"""在orm中 直接写在查询频率较高的表中"""
"""
ManyToManyField不会在表中创建实际的字段 而是告诉django orm自动创建第三张关系表
ForeignKey、OneToOneField会在字段的后面自动添加_id后缀 如果你在定义模型类的时候自己添加
了该后缀那么迁移的时候还会再次添加_id_id 所以不要自己加_id后缀
ps:三个关键字里面的参数
to用于指定跟哪张表有关系 自动关联主键
to_field\to_fields 也可以自己指定关联字段
"""
#书籍
class Book(models.Model):
title = models.CharField(max_length=32)
price = models.DecimalField(max_digits=8,decimal_places=2)
# 一对多
publish = models.ForeignKey(to='Publish')
# 多对多
authors = models.ManyToManyField(to='Author') # 自动创建书籍和作者的第三张关系表
#出版
class Publish(models.Model):
title = models.CharField(max_length=32)
#作者
class Author(models.Model):
name = models.CharField(max_length=32)
# 一对一
author_detail = models.OneToOneField(to='AuthorDetail')
#作者信息
class AuthorDetail(models.Model):
addr = models.CharField(max_length=32)
phone = models.BigIntegerField()
ORM外键字段操作
一对一,一对多(OneToOneField,ForeignKey)
添加外键字段值:
#第一种方法
models.Book.objects.create(title='JAVA',price=123456,publish_id=1) # 直接填写关联数据的主键值
#第二种方法
publish_obj = models.Publish.objects.filter(pk=2).first() # 获取外键对象
models.Book.objects.create(title='JS',price=11111,publish=publish_obj)
修改外键字段值:
#第一种方法
models.Book.objects.filter(pk=1).update(publish_id=2) # 直接修改publish_id的值
#第二种方法
publish_obj = models.Publish.objects.filter(pk=2).first() # 先获取对象,这里是修改出版社那么要先获取对应出版社对象
models.Book.objects.filter(pk=1).update(publish=publish_obj) # 修改publish
多对多(ManyToManyField)
# 添加关系
#第一种方法
book_obj = models.Book.objects.filter(pk=2).first() # 先获取对应书籍对象
book_obj.authors.add(1) # 然后给书籍对象的authors字段传入作者的id # 在第三张关系表中添加数据
book_obj.authors.add(1, 3) #可以直接填写数据主键值
#第二种方法
author_obj1 = models.Author.objects.filter(pk=3).first() # 先获取作者对象
author_obj2 = models.Author.objects.filter(pk=4).first()
book_obj.authors.add(author_obj1)
book_obj.authors.add(author_obj1,author_obj2) # 会在第三张表中添加2条数据(2,3)(2,4)
#修改关系
book_obj = models.Book.objects.filter(pk=1).first()
book_obj.authors.set([3, ])
book_obj.authors.set([1, 2])
author_obj1 = models.Author.objects.filter(pk=3).first()
author_obj2 = models.Author.objects.filter(pk=4).first()
book_obj.authors.set([author_obj1, ])
book_obj.authors.set([author_obj1, author_obj2])
#移除关系
book_obj = models.Book.objects.filter(pk=1).first()
book_obj.authors.remove(3)
book_obj.authors.remove(3,4)
author_obj1 = models.Author.objects.filter(pk=1).first()
author_obj2 = models.Author.objects.filter(pk=2).first()
book_obj.authors.remove(author_obj1)
book_obj.authors.remove(author_obj1,author_obj2)
#清空关系
book_obj = models.Book.objects.filter(pk=1).first()
book_obj.authors.clear()
1.第三张关系表创建数据
book_obj = models.Book.objects.filter(pk=1).first()
book_obj.authors.add()
括号内可以放主键值也可以放数据对象 并且都支持多个
2.第三张关系表修改数据
book_obj.authors.set()
括号内必须是一个可迭代对象 元素同样支持主键值或者数据对象
3.第三张关系表删除数据
book_obj.authors.remove()
括号内可以放主键值也可以放数据对象 并且都支持多个
4.第三张关系表清空指定数据
book_obj.authors.clear()
括号内无需传值 直接清空当前表在第三张关系表中的绑定记录
正向查询和反向查询
如果一张表有外键字段,并且是从这张表开始查询的,那么就叫作正向查询。
相反的,如果从关联表开始查询的,就叫反向查询。
由书籍查询出版社 外键字段在书籍表中 那么书查出版社就是'正向'
由出版社查询书籍 外键字段不在出版社表 那么出版社查书就是'反向'
"""
查询口诀
正向查询按外键字段名
反向查询按表名小写
"""
多表查询
表信息
#书籍
class Book(models.Model):
title = models.CharField(max_length=32)
price = models.DecimalField(max_digits=8,decimal_places=2)
# 一对多
publish = models.ForeignKey(to='Publish')
# 多对多
authors = models.ManyToManyField(to='Author') # 自动创建书籍和作者的第三张关系表
#出版
class Publish(models.Model):
title = models.CharField(max_length=32)
#作者
class Author(models.Model):
name = models.CharField(max_length=32)
# 一对一
author_detail = models.OneToOneField(to='AuthorDetail')
#作者信息
class AuthorDetail(models.Model):
addr = models.CharField(max_length=32)
phone = models.BigIntegerField()
基于对象的跨表查询(子查询)
正向查询
1.查询Python编程书籍对应的出版社
(1)先获取书籍对象
book_obj = models.Book.objects.filter(title='Python编程').first()
(2)进行跨表查询,从书籍找到出版社是正向查询,使用外键字段名
res = book_obj.publish # 返回的是对应的出版社对象
print(res.title) # 上海出版社
2.查询python编程书籍创作的作者
# 首先先获取书籍对象
book_obj = models.Book.objects.filter(title='Python编程').first()
# 进行跨表查询,从书籍找到出版社是正向查询,使用外键字段名
# res = book_obj.authors
# print(res) # app01.Author.None # 此时返回none,如果返回有多个还需要加all()
res = book_obj.authors.all() # 返回多个对象
print(res) # <QuerySet [<Author: Author object>, <Author: Author object>]>
反向查询
3.查询上海出版社出版的书籍
#首先获取出版社对象
publish_obj = models.Publish.objects.filter(title='上海出版社').first()
#进行跨表查询,从出版社找到书籍是反向查询(外键不在出版社表中),使用表名小写
# res = publish_obj.book_set # 反向查询时表名小写还需要加上 _set
# print(res) # app01.Book.None
#由于一个出版社可以出版多本书籍,返回结果可能是多个,还需要加上 all()
res = publish_obj.book_set.all() #返回多个书籍对象
print(res) # <QuerySet [<Book: Book object>, <Book: Book object>]>
4.查询电话为1的作者(在一对一关系中的反向查询表名小写后不要跟 _set)
author_detail_obj = models.AuthorDetail.objects.filter(phone=1).first()
res = author_detail_obj.author # 返回作者对象
print(res.name) # 张三
基于双下划线的跨表查询(多表连接查询)
1.查询Python编程书籍对应的出版社名称
res = models.Book.objects.filter(title='Python编程').values('publish__title')
print(res) # <QuerySet [{'publish__title': '上海出版社'}]>
2.查询作者张三的手机号和地址
res = models.Author.objects.filter(name='张三').values('author_detail__phone','author_detail__addr')
print(res) # <QuerySet [{'author_detail__phone': 1, 'author_detail__addr': '上海'}]>
双下划线查询扩展
1.查询Python编程书籍对应的出版社名称
方法一:
res = models.Publish.objects.filter(book__title='Python编程') # 返回出版社对象<QuerySet [<Publish: Publish object>]>
print(res[0].title) # 上海出版社
方法二:
res = models.Publish.objects.filter(book__title='Python编程').values('title')
print(res) # <QuerySet [{'title': '上海出版社'}]>
print(res[0].get('title')) # 上海出版社
方法三:
res = models.Publish.objects.filter(book__title='Python编程').first()
print(res.title) # 上海出版社
2.查询作者王五的手机号和地址
res = models.AuthorDetail.objects.filter(author__name='王五').values('phone','addr')
print(res) # <QuerySet [{'phone': 3, 'addr': '北京'}]>
print(res[0].get('phone')) # 3
print(res[0].get('addr')) # 北京
'''连续跨表操作'''
1.查询python编程书籍对应的作者的手机号
res = models.Book.objects.filter(title='PYthon编程').values('authors__author_detail__phone')
print(res) # <QuerySet [{'authors__author_detail__phone': 1}, {'authors__author_detail__phone': 2}]>
如何查看SQL语句
方式1:如果结果集对象是queryset 那么可以直接点query查看
方式2:配置文件固定配置
适用面更广 只要执行了orm操作 都会打印内部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',
},
}
}