ORM联表

1. 神奇的双下划线查询

# 1.查询年龄大于20的用户
# res = models.User.objects.filter(age__gt=20).values('name')
# print(res)
"""
    __gt         大于
    __lt         小于
    __gte        大于等于
    __lte        小于等于
    """
# 2.查询年龄是18、22、25的用户
# res = models.User.objects.filter(age__in=[18, 22, 25]).values('name')
# print(res)
"""
    __in         成员运算
    """
# 3.查询年龄在18到30之间的用户
# res = models.User.objects.filter(age__range=[18, 30]).values('name')  # 包含18和26
# print(res)
"""
    __range      范围查询
    """
# 4.查询姓名中包含字母j的用户
# res = models.User.objects.filter(name__contains='j').values('name')
# res = models.User.objects.filter(name__icontains='j').values('name')
# print(res)
    """
    __contains      区分大小写
    __icontains     忽略大小写
    """
# 5.其他方法补充
"""
    __startswith    以...开头
    __endswith      以...结尾
    __regex         正则
    """
# print(models.User.objects.filter(name__startswith='j').values('name'))
# print(models.User.objects.filter(name__endswith='n').values('name'))
# 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         按照月份筛选数据
    ...
    """

代码示例

    print(models.User.objects.filter(age__gt=20).values('name'))
    print(models.User.objects.filter(age__in=[18, 22, 25]).values('name'))
    print(models.User.objects.filter(age__range=[18, 30]).values('name'))
    print(models.User.objects.filter(name__contains='j').values('name'))
    print(models.User.objects.filter(name__icontains='j').values('name'))
    print(models.User.objects.filter(name__startswith='j').values('name'))
    print(models.User.objects.filter(name__endswith='n').values('name'))
    print(models.User.objects.filter(op_time__month=5).values('name'))
    print(models.User.objects.filter(op_time__year=2022).values('name'))

 

 

 

 

2. 外键字段的创建

"""
MySQL复习
关系的种类
    一对多关系
    多对多关系
    一对一关系
关系的判断
    换位思考
字段的位置
    一对多关系 外键字段建在多的一方
    多对多关系 外键字段建在第三张关系表中
    一对一关系 外键字段建在任意一方都可以 但是推荐建在查询频率较高的表中
"""
django orm创建表关系
  图书表
  出版社表
  作者表
  作者详情表
关系判断
    书与出版社
      一本书不能对应多个出版社
    一个出版社可以对应多本书
    # 一对多关系 书是多 出版社是一            ForeignKey
    '''django orm外键字段针对一对多关系也是建在多的一方 '''
    
  书与作者
      一本书可以对应多个作者
    一个作者可以对应多本书
    # 多对多关系                           ManyToManyField
    '''django orm外键字段针对多对多关系 可以不用自己创建第三张表'''
  作者与作者详情
      一个作者不能对应多个作者详情
    一个作者详情不能对个多个作者
    # 一对一关系                           OneToOneField
    '''django orm外键字段针对一对一关系 建在查询频率较高的表中'''
 
ManyToManyField不会在表中创建实际的字段 而是告诉django orm自动创建第三张关系表
ForeignKey、OneToOneField会在字段的后面自动添加_id后缀 如果你在定义模型类的时候自己添加了该后缀那么迁移的时候还会再次添加_id_id 所以不要自己加_id后缀


ps:三个关键字里面的参数
    to用于指定跟哪张表有关系 自动关联主键
    to_field\to_fields  也可以自己指定关联字段

 

3. 外键字段操作

# 一对多、一对一外键字段操作
  增
    publish_id=1             author_detail_id=1
    publish=publish_obj      author_detail=detail_obj
  改
    update(publish_id=3)         update(author_detail_id=3)
    update(publish=publish_obj)  update(author_detail=detail_obj)
 
# 多对多字段操作
  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()
        括号内无需传值 直接清空当前表在第三张关系表中的绑定记录

 

4. 多表查询

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

# 编写orm跟编写SQL语句一样 不要总想着一步到位!!!

 

5. 基于对象的跨表查询

"""基于对象的跨表查询本质就是子查询即分步操作即可"""
    # 1.查询数据分析书籍对应的出版社
    # 先获取书籍对象
    # book_obj = models.Book.objects.filter(title='数据分析').first()
    # 再使用跨表查询
    # res = book_obj.publish
    # print(res.name)

    # 2.查询python全栈开发对应的作者
    # 先获取书籍对象
    # book_obj = models.Book.objects.filter(title='python全栈开发').first()
    # 再使用跨表查询
    # res = book_obj.authors  # app01.Author.None
    # res = book_obj.authors.values('name', 'age')
    # print(res) 

    # 3.查询作者jason的详情信息
    # 先获取jason作者对象
    # author_obj = models.Author.objects.filter(name='jason').first()
    # 再使用跨表查询
    # res = author_obj.author_detail
    # print(res.phone)


    # 4.查询东方出版社出版的书籍
    # publish_obj = models.Publish.objects.filter(name='东方出版社').first()
    # res = publish_obj.book_set  # app01.Book.None
    # res = publish_obj.book_set.values('title','price')
    # print(res)


    # 5.查询jason编写的书籍
    # author_obj = models.Author.objects.filter(name='jason').first()
    # res = author_obj.book_set  # app01.Book.None
    # res = author_obj.book_set.values('title')
    # print(res)


    # 6.查询电话是110的作者
    # author_detail_obj = models.AuthorDetail.objects.filter(phone=110).first()
    # res = author_detail_obj.author
    # print(res)

 

 

 

6. 基于双下划线的跨表查询

    # 基于对象的跨表查询
    # 子查询,联表查询
    # 1.查询'如何掌握富婆'书籍对应的出版社
    print(models.Book.objects.filter(title='如何掌握富婆').values('publish__name'))
    # 2.查询'linux'对应的作者姓名和年龄 
    print(models.Book.objects.filter(title='linux').values('authors__name', 'authors__age'))
    # 3.查询作者jason的手机号和地址
    print(models.Author.objects.filter(name='jason').values('author_detail__phone', 'author_detail__addr'))
    # 4.查询东方出版社出版的书籍名称和价格
    print(models.Publish.objects.filter(name='东方出版社').values('book__title', 'book__price'))
    # 5.查询jason编写的书籍名称
    print(models.Author.objects.filter(name='jason').values('book__title'))
    # 6.查询电话是110的作者的姓名和年龄
    print(models.AuthorDetail.objects.filter(phone='110').values('author__name', 'author__age'))

 

 

 

7. 双下线查询扩展

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

'''手上有条件所在的表可以不被models点 直接点最终的目标数据对应的表'''
    # 1.查询'如何掌握富婆'书籍对应的出版社
    print(models.Publish.objects.filter(book__title='如何掌握富婆').values('name'))
    # 2.查询'linux'对应的作者姓名和年龄
    print(models.Author.objects.filter(book__title='linux').values('name', 'age'))
    # 3.查询作者jason的手机号和地址
    print(models.AuthorDetail.objects.filter(author__name='jason').values('phone', 'addr'))
    # 4.查询东方出版社出版的书籍名称和价格
    print(models.Book.objects.filter(publish__name='东方出版社').values('title', 'price'))
    # 5.查询jason编写的书籍名称
    print(models.Book.objects.filter(authors__name='jason').values('title'))
    # 6.查询电话是110的作者的姓名和年龄
    print(models.Author.objects.filter(author_detail__phone='110').values('name', 'age'))

# 连续跨表操作
# 查询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)
"""

 

 

 

 

8. 如何查看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',
            },
        }
    }

 

posted @ 2022-05-17 20:13  thrombus  阅读(56)  评论(0)    收藏  举报