zoukankan      html  css  js  c++  java
  • Djiango orm 多表查询

    多表操作

    一、Django多表orm设计规则

    1. 关联的表之间建议建立外键,但可以取消关联关系(db_constraint=False)
    2. 关联表之间的外键字段建议采用对应类名的全小写
    3. 采用关联表的主键或对象均能进行操作
    
    # 例表设计:
    # 书籍 Book: id name price publish_date publish author(多对多关联字段)
    # 出版社 Publish: id name address
    # 作者 Author: id name author_detail
    # 作者详情 AuthorDetail: id age telephone info

    modles设计:

    # 一对多:出版社(一) 书籍(多,外键在多的一方,依赖于出版社)
    # 一对一:作者详情(一) 作者(一,外键在任意一方均可,一旦外键放在作者中,作者依赖于作者详情)
    # 多对多:作者(多)书籍(多)建立关系表(存放两个表的外键信息 => 将建表转化为关系对应字段)
    
    # Book书籍:id  name  price  publish_date  publish(publish_id)
    class Book(models.Model):
        id = models.AutoField(primary_key=True)
        name = models.CharField(max_length=20)
        price = models.DecimalField(max_digits=5, decimal_places=2)
        publish_date = models.DateField()
        publish = models.ForeignKey(to='Publish', to_field='id')
        # 多对多关系字段,该字段不会再book表中形成字段,是用来创建关系表的
        author = models.ManyToManyField(to='Author')
    
    # Author作者:id  name
    class Author(models.Model):
        id = models.AutoField(primary_key=True)
        name = models.CharField(max_length=20)
        # author_detail = models.ForeignKey(to='AuthorDetail', to_field='id', unique=True)
        author_detail = models.OneToOneField(to='AuthorDetail', to_field='id')
    
    # AuthorDetail作者详情: id  age  telephone  info
    class AuthorDetail(models.Model):
        id = models.AutoField(primary_key=True)
        age = models.IntegerField()
        telephone = models.IntegerField()
        # 存大文本
        info = models.TextField()
    
    # Publish出版社:id  name  address
    class Publish(models.Model):
        id = models.AutoField(primary_key=True)
        name = models.CharField(max_length=20)
        address = models.CharField(max_length=64)
    View Code

    二、一对多关系

    1、规则:

    1. 关系中 『多』 依赖于 『一』
    2. Django 1.x外键关联默认有级联删除,2.x需要手动明确外键的级联删除(on_delete=models.CASCADE)

    2、增删改操作

    # 1、增
    # 先有出版社,才有书籍
    publish = Publish.objects.create(name="老男孩出版社", address="上海核心基地")
    # 外键为关联对象
    Book.objects.create(name='死亡Python', price=88.88,  publish_date='2018-8-8', publish=publish)   # 此处返回的是一个对象
    
    id = Publish.objects.create(name="小女孩出版社", address="宇宙中心").id
    # 外键字段为关联对象主键
    Book.objects.create(name='灭霸Linux', price=120.00, publish_date='2015-8-8', publish_id=id)
    
    # 2、删
    # 删除出版社,默认有级联删除,出版社出版的数据全会被删除
    Publish.objects.first().delete()
    
    # 3、改
    # 书籍的出版社修改必须为已存在的出版社
    publish = Publish.objects.create(name="Owen出版社", address="御花园")
    Book.objects.filter(pk=1).update(publish=publish)  # pk代表主键

    三、一对一关系

    1、规则

        通过外键所在表决定依赖关系,有外键的表依赖于外键所对应的另一张表。

    2、增删改操作

    # 操作规则同一对多关系,有外键的表 依赖于 另一张表
    
    # 增:遵循操作顺序
    author_detail = AuthorDetail.objects.create(age=18, telephone=13860357890, info="")
    Author.objects.create(name='Sandy', author_detail=author_detail)
    
    # 删:拥有级联删除
    AuthorDetail.objects.first().delete()
    
    # 改:一般不考虑该关联字段

    四、多对多关系

    1、规则:

      1. 多对多关系存在关系表,关系表建议采用ManyToManyField字段处理;
      2. 需要手动创建关系表时,在字段中明确through与through_field值。

    2、增删改操作:

    通过关系表字段存在的类的对象获取关系表 book.author
    b1 = Book.objects.first()  # type: Book
    b2 = Book.objects.all()[1]  # type: Book
    a1 = Author.objects.first()  # type: Author
    a2 = Author.objects.all()[1]  # type: Author
    
    # 增:为书籍添加作者的主键或对象们
    # book.author.add(*args)  # 此处的book为Book的对象
    b1.author.add(a1.id, a2.id)
    b2.author.add(a1, a2)
    
    # 删:删除书籍已有作者的主键或对象们
    #  book.author.remove(*args)   # 此处的book为Book的对象
    b1.author.remove(a1)
    b1.author.remove(a2.id)
    
    # 改:清空并添加作者的主键或对象 | 设置作者的主键或对象形式的列表
    # book.author.clear()      # 此处的book为Book的对象
    b1.author.clear()
    
    # book.author.add(*args)    # 此处的book为Book的对象
    b1.author.add(a1)
    
    # book.author.set([*args])    # 此处的book为Book的对象
    b2.author.set([a2.id, a3.id])

    五、跨表查询规则

      1. 正向逆向概念:从存放外键的表到关系表称之为正向跨表查询,反之称之为逆向查询;
      2. 正向查询通过外键属性名进行跨表查询;
      3. 逆向查询通过关联表对应类名小写进行跨表查询,逆向查询遇到多条结果,在类名后再添加_set

     六、基于对象的跨表查询

    在跨表查询的规则上,跨表查询的结果为多条数据时需要在字段后添加_set
    
    # 一对一
    author = Author.objects.first()  # 查询得到作者对象
    author_detail = author.author_detail  # 基于对象跨表获取作者详情对象,正向通过字段名 author_detail
    author = author_detail.author  # 基于对象跨表获取作者对象,逆向通过表名小写 author
    
    # 一对多
    book = Book.objects.first()  # 查询得到书籍对象
    publish = book.publish  # 获取出版社对象,正向通过字段名 publish
    book_list = publish.book_set.all()  # 获取书籍对象们,逆向通过表名小写 book,多条数据添加_set
    
    # 多对多
    book = Book.objects.first()  # 查询得到书籍对象
    author_list = book.author   # 获取作者对象们,正向通过字段名 author
    
    author = Author.objects.first()
    book_list = author.book_set  # 获取书籍对象们,逆向通过表名小写 book,多条数据添加_set
    
    # 多级跨表
    # 案例一:某作者出版的第一本书的出版社名字
    author.book_set.first().publish.name

     七、基于下划线的跨表查询

    满足跨表查询规则
    filter方法与values方法支持__查询规则
    
    # 案例
    
    # 两表关联:查询所有小于18岁作者的名字与实际年龄
    authors_dic = Author.objects.filter(author_detail__id__gt=0).values('name', 'author_detail__age')
    
    # 多表关联:查询出版社在上海的出版过的所有书的 作者姓名、作者电话、具体出版社名 的相关信息
    info_dic = Book.objects.filter(publish__address__contains="上海").values('author__name', 'author__author_detail__telephone', 'publish__name')
  • 相关阅读:
    有一群志同道合的程序员朋友是怎样的体验?
    hdu1387 模拟队列
    hau 1870 愚人节的礼物(栈)
    hdu1509 优先队列
    hdu1837 看病要排队(优先队列)
    hdu 1237 简单计算器(栈处理)
    hdu1022 模拟栈
    又一个错误的认知!
    jmeter+ant+jenkins 接口自动化测试持续集成(送源码)
    P1197 [JSOI2008]星球大战
  • 原文地址:https://www.cnblogs.com/peng-zhao/p/10485386.html
Copyright © 2011-2022 走看看