django里的orm操作

双下划线查询

orm创建外键关系

外键字段的增删改查

正反向的概念

多表查询

双下划线查询

# 1.查询年龄大于20的用户
# res = models.User.objects.filter(age__gt=20)
# print(res)
"""
    __gt         大于
    __lt         小于
    __gte        大于等于
    __lte        小于等于
    """
# 2.查询年龄是18、22、25的用户
# res = models.User.objects.filter(age__in=[18, 22, 25])
# print(res)
"""
    __in         成员运算
    """
# 3.查询年龄在18到26之间的用户
# res = models.User.objects.filter(age__range=[18, 26])  # 包含18和26
# print(res)
"""
    __range      范围查询
    """
# 4.查询姓名中包含字母j的用户
# res = models.User.objects.filter(name__contains='j')
# res = models.User.objects.filter(name__icontains='j')
# print(res)
"""
    __contains      区分大小写
    __icontains     忽略大小写
    """
# 5.其他方法补充
"""
    __startswith	>>>>>>>查询以什么开头
    __endswith		>>>>>>>查询以什么结尾的
    __regex			>>>>>>>>大小写敏感的判断某字段的值是否满足正则表达式的条件
    """
# 6.查询月份是5月的数据
# res = models.User.objects.filter(op_time__month=5)
# print(res)
# 查询年份是22年的数据
res = models.User.objects.filter(op_time__year=2022)
print(res)
"""
    __year          按照年份筛选数据
    __month         按照月份筛选数据
    ...
    """

外键字段的创建

"""
MySQL复习
关系的种类
	一对多关系
	多对多关系
	一对一关系
关系的判断
	换位思考
字段的位置
	一对多关系 外键字段建在多的一方
	多对多关系 外键字段建在第三张关系表中
	一对一关系 外键字段建在任意一方都可以 但是推荐建在查询频率较高的表中
"""
django orm创建表关系
	图书表
  出版社表
  作者表
  作者详情表
关系判断
	书与出版社
  	一本书不能对应多个出版社
    一个出版社可以对应多本书
    # 一对多关系(ForeignKey) 书是多 出版社是一			
    '''django orm外键字段针对一对多关系也是建在多的一方 '''
    #书与出版社的外键字段:
     pubilsh = models.ForeignKey(to='Pubilsh')   # 默认关联的就是1主键字段
     # 书与作者的外键字段
     authors = models.ManyToManyField(to='Author')  # 自动1创建书和作者的第三张关系表
  书与作者
  	一本书可以对应多个作者
    一个作者可以对应多本书
    # 多对多关系 (ManyToManyField)										
    '''django orm外键字段针对多对多关系 可以不用自己创建第三张表'''
  作者与作者详情
  	一个作者不能对应多个作者详情
    一个作者详情不能对个多个作者
    # 一对一关系	(OneToOneField)										
    '''django orm外键字段针对一对一关系 建在查询频率较高的表中'''
 	# 作者与作者详情的外键字段
    author_datail = models.OneToOneField(to='AuthorDetail')
    
    ps:三个关键字里面的参数
  	to用于指定跟哪张表有关系 自动关联主键
    to_field\to_fields  也可以自己指定关联字段
    
ManyToManyField不会在表中创建实际的字段 而是告诉django orm自动创建第三张关系表
ForeignKey、OneToOneField会在字段的后面自动添加_id后缀 如果你在定义模型类的时候自己添加了该后缀那么迁移的时候还会再次添加_id_id 所以不要自己加_id后缀



外键字操作

# 一对一、一对多外键字段操作
	# 增
      新增一本书
   # models.Book.objects.create(title='聊斋志异',price=1799.22,pubilsh_id=1)
  	publish_id=1(可以直接传主键值)
    
   # publish_obj = models.Pubilsh.objects.filter(pk=2).first()
    models.Book.objects.create(title='狂人日记',price=1699.36,publish=publish_obj)
    publish=publish_obj  (可以直接传数据对象)
    
    author_detail_id=1(可以直接写id值)
    author_detail=detail_obj(也可以传数据对象)
    
  # 改
  	update(publish_id=3)	update(author_detail_id=3)
    update(publish=publish_obj)  update(author_detail=detail_obj)
 
# 多对多字段操作
	1.第三张关系表创建数据(add)
	book_obj = models.Book.objects.filter(pk=1).first()
    book_obj.authors.add() 
  	add是先通过上面那个对象,然后通过对象点来的,括号内可以放主键值也可以放数据对象 并且都支持多个
  2.第三张关系表修改数据(set)
	book_obj = models.Book.objects.filter(pk=1).first()
  2.1	book_obj.authors.set()
  2.2 author_obj = models.Author.objects.filter(pk=3).first()
      book_obj.authoes.set([author_obj, ])
    	括号内必须是一个可迭代对象(列表或字典等) 元素同样支持主键值或者数据对象
  3.第三张关系表删除数据(remove)
  	book_obj.authors.remove()
    	括号内可以放主键值也可以放数据对象 并且都支持多个
  4.第三张关系表清空指定数据(clear)
  	book_obj.authors.clear()
    	括号内无需传值 直接清空当前表在第三张关系表中的绑定记录

多表查询

"""
MySQL多表查询思路
	子查询
		将SQL语句用括号括起来当做条件使用
	连表操作
		inner join\left join\right join\union
django orm本质还是使用的上述两种方法
	子查询>>>:基于对象的跨表查询
	连表操作>>>:基于双下划线的跨表查询
"""
# 正反向的概念
	核心在于当前数据对象是否含有外键字段 有则是正向 没有则是反向
	正向
  	eg:
      由书籍查询出版社 外键字段在书籍表中 那么书查出版社就是'正向'
      由书籍查询作者 外键字段在书籍表中 那么书查作者就是'正向'
      由作者查询作者详情 外键字段在作者表中 那么也是'正向'
  反向
  	eg:
      由出版社查询书籍 外键字段不在出版社表 那么出版社查书就是'反向'
      ...
 	"""
 	查询口诀
 		正向查询按外键字段名
 		反向查询按表名小写
 	"""


models文件

from django.db import models

# Create your models here.

# 图书表
class Book(models.Model):
    title = models.CharField(max_length=32,verbose_name='书名')
    price = models .DecimalField(max_digits=8,decimal_places=2,verbose_name='价格')  # 价格总共有八位数,小数点后面占两位
    pubilsh_time = models.DateField(auto_now_add=True,verbose_name='出版日期')
# 书与出版社的外键字段(一对多)
    pubilsh = models.ForeignKey(to='Pubilsh')   # 默认关联的就是1主键字段
 # 书与作者的外键字段(多对多)
    authors = models.ManyToManyField(to='Author')  # 自动1创建书和作者的第三张关系表


    def __str__(self):
        return '书籍对象:%s' % self.title

# 出版社表
class Pubilsh(models.Model):
    name = models.CharField(max_length=32,verbose_name='出版社名字')
    addr = models.CharField(max_length=64,verbose_name='出版社地址')

    def __str__(self):
        return '出版社对象:%s' % self.name

# 作者表
class Author(models.Model):
    name = models.CharField(max_length=32,verbose_name='作者姓名')
    age = models.IntegerField(verbose_name='年龄')

# 作者与作者详情的外键字段(一对一)
    author_detail = models.OneToOneField(to='AuthorDetail')

    def __str__(self):
        return '作者对象:%s' % self.name

# 作者详情表
class AuthorDetail(models.Model):
    phone = models.BigIntegerField(verbose_name='手机号')
    addr = models.CharField(max_length=64,verbose_name='家庭地址')

    def __str__(self):
        return '作者详情对象:%s' % self.addr




基于对象的跨表查询

"""基于对象的跨表查询本质就是子查询即分步操作即可"""
	# 1.查询数据分析书籍对应的出版社
    # 先获取书籍对象
    # book_obj = models.Book.objects.filter(title='数据分析').first()
    # 再使用跨表查询
    # res = book_obj.publish
    # print(res)  # 出版社对象:北方出版社
    # 2.查询python全栈开发对应的作者
    # 先获取书籍对象
    # book_obj = models.Book.objects.filter(title='python全栈开发').first()
    # 再使用跨表查询
    # res = book_obj.authors  # app01.Author.None 之所以会出现这种情况是因为这是多对多关系,
    # res = book_obj.authors.all()
    # print(res)  # <QuerySet [<Author: 作者对象:jason>, <Author: 作者对象:jerry>]>
    # 3.查询作者jason的详情信息
    # 先获取jason作者对象
    # author_obj = models.Author.objects.filter(name='jason').first()
    # 再使用跨表查询
    # res = author_obj.author_detail
    # print(res)  # 作者详情对象:芜湖

    # 4.查询东方出版社出版的书籍
    # publish_obj = models.Publish.objects.filter(name='东方出版社').first()
    # res = publish_obj.book_set  # app01.Book.None
    # res = publish_obj.book_set.all()
    # print(res)  # <QuerySet [<Book: 书籍对象:linux云计算>, <Book: 书籍对象:聊斋志异>]>
    # 5.查询jason编写的书籍
    # author_obj = models.Author.objects.filter(name='jason').first()
    # res = author_obj.book_set  # app01.Book.None
    # res = author_obj.book_set.all()
    # print(res)  # <QuerySet [<Book: 书籍对象:golang高并发>, <Book: 书籍对象:python全栈开发>]>
    # 6.查询电话是110的作者
    author_detail_obj = models.AuthorDetail.objects.filter(phone=110).first()
    res = author_detail_obj.author
    print(res)  # 作者对象:jason

基于双下划线的跨表查询

"""基于双下划线的跨表查询本质就是连表操作"""
# 基于双下划线的跨表查询
    """
    查询数据分析书籍对应的价格和出版日期
    models.Book.objects.filter(title='数据分析').values('price','publish_time')
    """
    '''手上有什么条件就先拿models点该条件对应的表名'''
    # 1.查询数据分析书籍对应的出版社名称
    # res = models.Book.objects.filter(title='数据分析').values('publish__name', 'publish__addr')
    # print(res)  # <QuerySet [{'publish__name': '北方出版社', 'publish__addr': '北京'}]>
    # 2.查询python全栈开发对应的作者姓名和年龄
    # res = models.Book.objects.filter(title='python全栈开发').values('authors__name','authors__age')
    # print(res)  # <QuerySet [{'authors__name': 'jason', 'authors__age': 18}, {'authors__name': 'jerry', 'authors__age': 29}]>
    # 3.查询作者jason的手机号和地址
    # res = models.Author.objects.filter(name='jason').values('author_detail__phone','author_detail__addr')
    # print(res)  # <QuerySet [{'author_detail__phone': 110, 'author_detail__addr': '芜湖'}]>

    # 4.查询东方出版社出版的书籍名称和价格
    # res = models.Publish.objects.filter(name='东方出版社').values('book__title','book__price')
    # print(res)  # <QuerySet [{'book__title': 'linux云计算', 'book__price': Decimal('24888.44')}, {'book__title': '聊斋志异', 'book__price': Decimal('16987.22')}]>
    # 5.查询jason编写的书籍名称和日期
    # res = models.Author.objects.filter(name='jason').values('book__title', 'book__publish_time')
    # print(res)  # <QuerySet [{'book__title': 'golang高并发', 'book__publish_time': datetime.date(2022, 6, 7)}, {'book__title': 'python全栈开发', 'book__publish_time': datetime.date(2022, 2, 28)}]>
    # 6.查询电话是110的作者的姓名和年龄
    # res = models.AuthorDetail.objects.filter(phone=110).values('author__name','author__age')
    # print(res)  # <QuerySet [{'author__name': 'jason', 'author__age': 18}]>

双下线查询扩展

"""基于双下划线的跨表查询的结果也可以是完整的数据对象"""

'''手上有条件所在的表可以不被models点 直接点最终的目标数据对应的表'''
		# 1.查询数据分析书籍对应的出版社名称
    # res = models.Publish.objects.filter(book__title='数据分析')
    # print(res)  # <QuerySet [<Publish: 出版社对象:北方出版社>]>
    # res = models.Publish.objects.filter(book__title='数据分析').values('name')
    # print(res)  # <QuerySet [{'name': '北方出版社'}]>
    # 2.查询python全栈开发对应的作者姓名和年龄
    # res = models.Author.objects.filter(book__title='python全栈开发').values('name','age')
    # print(res)  # <QuerySet [{'name': 'jason', 'age': 18}, {'name': 'jerry', 'age': 29}]>
    # 3.查询作者jason的手机号和地址
    # res = models.AuthorDetail.objects.filter(author__name='jason').values('phone','addr')
    # print(res)  # <QuerySet [{'phone': 110, 'addr': '芜湖'}]>
    # 4.查询东方出版社出版的书籍名称和价格
    # res = models.Book.objects.filter(publish__name='东方出版社').values('title','price')
    # print(res)  # <QuerySet [{'title': 'linux云计算', 'price': Decimal('24888.44')}, {'title': '聊斋志异', 'price': Decimal('16987.22')}]>
    # 5.查询jason编写的书籍名称和日期
    # res = models.Book.objects.filter(authors__name='jason').values('title','publish_time')
    # print(res)  # <QuerySet [{'title': 'golang高并发', 'publish_time': datetime.date(2022, 6, 7)}, {'title': 'python全栈开发', 'publish_time': datetime.date(2022, 2, 28)}]>
    # 6.查询电话是110的作者的姓名和年龄
    # res = models.Author.objects.filter(author_detail__phone=110).values('name','age')
    # print(res)  # <QuerySet [{'name': 'jason', 'age': 18}]>
 


# 连续跨表操作
# 查询python全栈开发对应的作者的手机号
# res = models.Book.objects.filter(title='python全栈开发').values('authors__author_detail__phone')
# print(res)  # <QuerySet [{'authors__author_detail__phone': 110}, {'authors__author_detail__phone': 140}]>
res1 = models.AuthorDetail.objects.filter(author__book__title='python全栈开发').values('phone')
print(res1)  # <QuerySet [{'phone': 110}, {'phone': 140}]>


"""
可能出现的不是疑问的疑问:如何获取多张表里面的字段数据
res = models.Book.objects.filter(title='python全栈开发').values('authors__author_detail__phone','authors__name','title')
print(res)
"""

如何查看SQL语句

方式1:如果结果集对象是queryset 那么可以直接点query查看
方式2:配置文件固定配置
  	适用面更广 只要执行了orm操作 都会打印内部SQL语句