zoukankan      html  css  js  c++  java
  • 第十七篇 ORM跨表查询和分组查询---二次剖析

    ORM跨表查询和分组查询---二次剖析

    阅读目录(Content)

    创建表(建立模型)

    实例:我们来假定下面这些概念,字段和关系

    作者模型:一个作者有姓名和年龄。

    作者详细模型:把作者的详情放到详情表,包含生日,手机号,家庭住址等信息。作者详情模型和作者模型之间是一对一的关系(one-to-one)

    出版商模型:出版商有名称,所在城市以及email。

    书籍模型: 书籍有书名和出版日期,一本书可能会有多个作者,一个作者也可以写多本书,所以作者和书籍的关系就是多对多的关联关系(many-to-many);一本书只应该由一个出版商出版,所以出版商和书籍是一对多关联关系(one-to-many)。

    模型建立如下:

    class Author(models.Model):
        nid = models.AutoField(primary_key=True)
        name=models.CharField( max_length=32)
        age=models.IntegerField()
     
        # 与AuthorDetail建立一对一的关系
        authorDetail=models.OneToOneField(to="AuthorDetail")
     
    class AuthorDetail(models.Model):
     
        nid = models.AutoField(primary_key=True)
        birthday=models.DateField()
        telephone=models.BigIntegerField()
        addr=models.CharField( max_length=64)
        
    class Publish(models.Model):
        nid = models.AutoField(primary_key=True)
        name=models.CharField( max_length=32)
        city=models.CharField( max_length=32)
        email=models.EmailField()
     
     
    class Book(models.Model):
     
        nid = models.AutoField(primary_key=True)
        title = models.CharField( max_length=32)
        publishDate=models.DateField()
        price=models.DecimalField(max_digits=5,decimal_places=2)
        keepNum=models.IntegerField()<br>    commentNum=models.IntegerField()
     
        # 与Publish建立一对多的关系,外键字段建立在多的一方
        publish=models.ForeignKey(to="Publish",to_field="nid")
     
        # 与Author表建立多对多的关系,ManyToManyField可以建在两个模型中的任意一个,自动创建第三张表
        authors=models.ManyToManyField(to='Author')  

    基于对象的跨表查询 

    ''''
    一对多:
    正向查询按字段
    Book--------------->Publish
    <---------------
    反向查询按表名小写_set
    '''''

    一对多查询(Publish与Book)

    正向查询按字段(看class里的publish = models.ForeignKey(to='Publish'))

     # (1) 查询id为2的书籍对应出版社的邮箱
        # Book.objects.filter(id=2)  是 一个   queryset对象,
        obj = Book.objects.filter(id=2).first()
        # 正向查询按字段
        ret= obj.publish.email

      filter 可以换成 get 但是get没有会报错

    反向查询(按表名:book_set):

    #(2) 沙河出版社出版过的所有的书籍的名字
    obj = Publish.objects.filter(name='沙河出版社').first()
    # 出版社找书籍  --反向查找
    obj1 = obj.book_set.all().values("name")

    '''
    多对多:
    正向查询按字段
    Book--------------->Author
    <---------------
    反向查询按表名小写_set
    反向查询按xxx
    '''

    多对多查询 (Author 与 Book)

    正向查询(按字段:authors)

    #(3)查询<涉哥开车来造>所有作者的名字
    
        obj = Book.objects.filter(name='涉哥开车来造').first()
        # 正向查询按字段
        ret = obj.author.all().values('name')

    反向查询(按表名:book_set)

    #(4) 查询杨刚出版的书籍个数
        obj=Author.objects.filter(name='杨刚').first()
        # 出版社找书籍  --反向查找
        ret = obj.book_set.all().count()

    一对一查询(Author 与 AuthorDetail)


    '''
    一对一:
    正向查询按字段
    Book--------------->Author
    <---------------
    反向查询按表名小写

    '''
    正向查询按字段
    # (5)查询杨刚的手机号
        obj = Author.objects.filter(name='杨刚').first()
        # 正向查询按字段
        ret = obj.auther_detail.tele
    反向查询按表名小写
     #(6) 住在北京的作者的名字
    
        obj = AuthorDetail.objects.filter(addr='北京').first()
        # 反向查询按表名小写
        ret = obj.author.name
        print(ret)

    注意:

    你可以通过在 ForeignKey() 和ManyToManyField的定义中设置 related_name 的值来覆写 FOO_set 的名称。例如,如果 Article model 中做一下更改: publish = ForeignKey(Blog, related_name='bookList'),

    基于双下划线的跨表查询 

    Django 还提供了一种直观而高效的方式在查询(lookups)中表示关联关系,它能自动确认 SQL JOIN 联系。要做跨关系查询,就使用两个下划线来链接模型(model)间关联字段的名称,直到最终链接到你想要的 model 为止

    关键点:正向查询按字段,反向查询按表名

    # (1)查询价格为111的书籍对应出版社的邮箱
        obj = Book.objects.filter(price=111).values('publish__email')
        print(obj)
    # (2) 沙河出版社出版过的所有的书籍的名字
        obj1 = Publish.objects.filter(name='沙河出版社').values('book__author__name')
        print(obj1)
    # (3)查询<涉哥开车来造>所有作者的名字
        obj2 = Book.objects.filter(name='涉哥开车来造').values('author__name')
        print(obj2)
     # (4) 查询杨刚出版的书籍个数
        obj3=Author.objects.filter(name='杨刚').values('book__name').count()
        print(obj3)
    # (5)查询杨刚的手机号
        obj4 = Author.objects.filter(name='杨刚').values('auther_detail__tele')
        print(obj4)
      # (6) 住在北京的作者的名字
        obj5 = AuthorDetail.objects.filter(addr='北京').values('author__name')
        print(obj5)

    分组查询

    多表查询

        #(1) 每一个出版社的名字以及对应出版书籍个数
        obj = Publish.objects.all().annotate(c=Count("book__name")).values("name","c")
        print(obj)
      # (2)查询每一个作者的名字以及对应书籍的平均价格
        obj1 = Author.objects.all().annotate(c=Avg('book__price')).values('name','c')
        print(obj1)
        # (3)查询每一本书 的名字以及作者的个数
        obj2 = Book.objects.all().annotate(c=Count("author")).values("name","c")
        print(obj2)

    单表查询

    # 单表查询
        ret = Book.objects.values("name").annotate(c=Count("*"))
        print(ret)
  • 相关阅读:
    spring属性注入
    spring的bean标签属性
    spring三种实例化bean的方式
    测试环境部署
    sql server将字符串转换为 uniqueidentifier 时失败
    mybatis parametertype 多个参数
    ORACLE-023:令人烦恼的 ora-01722 无效数字
    PostMan使用教程
    sqlserver复制表数据到另一个表
    to_number()函数的用法
  • 原文地址:https://www.cnblogs.com/a438842265/p/8858490.html
Copyright © 2011-2022 走看看