zoukankan      html  css  js  c++  java
  • Django ORM多表操作

    ORM的注意事项

    • nid = models.AutoField(primary_key=True) ID字段是自动添加的,需要自定义变量名可以自己填写.
    • 对于外键字段,Django会在字段名上添加_id来创建数据库中的别名
    • 外链字段Foreignkey有一个null=true的设置,它允许外链接受空值null,可以给赋空值None.

    多表关系的操作概要

    • 1对1的关系在两张表任意一张建立关联字段并且加Unique,比如
    作者表 author
     id  name  age
      1  alex  18
      2  blex  30
      3  clex  25
    
    作者个人信息表 authordetail
      id  addr  gender  tel  author_id(Unique)
      1    北京  男      123     1
      2    南京  女      1234    2
      3    上海  人妖    3311    3
    
    create table authordetail(
      id int primary key auto_increment,
      addr varchar(20),
      gender enum("male","female"),
      tel int(11)
      author_id int unique,
    
    );
    
    
    • 1对多的关系 需要在多个关系的表中建立关联字段
    出版社 publish
     id  name      book
      1  北京出版社  18
      2  南京出版社  30
      3  天津出版社  25
    
    create table publish(
      id int primary key auto_increment,
      name varchar(20)
    );
    
    
    书籍  book  在书籍和出版社对应关系中,一个出版社会出版多本书籍,因此把多个出版社id放在book表中创建一对多的关系,并且==要建立约束==,创建关系是为了查询,创建约束是为了防止产生脏数据
      id bookname  price  publish_id
      1  python      10        1
      2  java        20        1
      3  go          58        2
      4  php         79        3
     
    create table book(
      id int primary key auto_increment,
      bookname varchar(20),
      price    decimal(8,2),
      publish_id int,
      foreign key(publish_id) reference book(id),
    
    
    );
    
    • 多对多的关系 创建第三张关系表
    书籍 book
     id  name      price    publish_id
      1  python      18          1
      2  java        30          1
      3  go          25          2
    
    create table book(
      id int primary key auto_increment,
      name varchar(32),
      price decimal(5,2),
      publish_id int,
      foreign key (publish_id) reference publish(id),
    );
    
    
    作者表 author
     id  name  age
      1  alex  18
      2  blex  30
      3  clex  25
    
    create table author(
      id int primary key auto_increment,
      name varchar(32),
      age int,
    );
    
    做着书籍关系表 book2auther
    
      id  book_id  author_id
      1      1        1
      2      1        2
      3      2        1
      4      3        2
    create table book2auther(
      id int primary key auto_increment,
      book_id int,
      author_id int,
      foreign key (book_id) reference book(id),
      foreign key (author_id) reference author(id),
    );
    
    
    
    create table publish(
      id int primary key auto_increment,
      name varchar(20)
    );
    
    

    那么上面的sql语句在ORM中是怎么创建的呢,下面拿着SQL语法 举例在ORM中的语法

    1. 出版社和书本的一对多关系


    on_delete有6个可选值,分别是:
    CASCADE 删除级联,当父表的记录删除时,子表中与其相关联的记录也会删除。即:当一个老师被删除时,关联该老师的学生也会被删除。
    PROTECT 子表记录所关联的父表记录被删除时,会报ProtectedError异常。即:当一个学生所关联的老师被删除时,会报ProtectedError异常。
    SET_NULL 子表记录所关联的父表记录被删除时,将子表记录中的关联字段设为NULL,注意:需要允许数据表的该字段为NULL。
    SET_DEFAULT 子表记录所关联的父表记录被删除时,将子表记录中的关联字段设为一个给定的默认值。
    DO_NOTHING 子表记录所关联的父表记录被删除时,什么也不做。
    SET() 设置为一个传递给SET()的值或者一个回调函数的返回值,该参数用得相对较少。

    2. 作者和作者详情的一对一关系

    3. 书本和作者多对多的关系


    我们可以看下手动创建的Book2Author 和ManyToMany创建的 book_author表,实现的效果是一样的.

    orm一对多表之添加记录操作

    class Publish(models.Model):
        nid = models.AutoField(primary_key=True)
        publish = models.CharField(max_length=32)
        def __str__(self):
            return self.publish
    
    class book(models.Model):
        id = models.AutoField(primary_key=True)
        title = models.CharField(max_length=20)
        price = models.DecimalField(max_digits=8, decimal_places=2)
        pub_date = models.DateField()
        publish = models.ForeignKey(to="Publish", to_field="nid",on_delete=models.CASCADE)
    

    出版社和图书的对应关系为 一个出版社对应多本书,把对应关系写在book类中
    出版社数据添加不多说,因为很简单,pub = models.Publish.objects.create(publish="南京出版社")
    图书中的添加语法有2种,因为book中的publish在数据库中会自动进行字符串拼接为publish_id

    • 第一种book = models.book.objects.create(title="c++",price=18,pub_date = "2012-05-07",publish_id=2) publish_id直接写死
    • 第二种如下,此时book.title是java,book.price是28,但是book.publish 其实就是pub这个对象了,他包含了出版社的信息,所以book.publish.publish就是出版社的名字(南京出版社)
    pub = models.Publish.objects.filter(publish="南京出版社").first()  #先对Publish表进行筛选出南京出版社的对象,再把这个对象放到publish的参数中去,等同于publish_id=南京的id
    book = models.book.objects.create(title="java",price=28,pub_date = "2014-05-07",publish=pub)
    

    orm多对多表之添加记录操作

    class Book(models.Model):
        id = models.AutoField(primary_key=True)
        title = models.CharField(max_length=32)
        price = models.DecimalField(max_digits=8, decimal_places=2)
        publish = models.ForeignKey(to="Publish", to_field="pid", on_delete=models.CASCADE)
        author = models.ManyToManyField(to="Author")
    
    class Author(models.Model):
        aid = models.AutoField(primary_key=True)
        name = models.CharField(max_length=32)
        age = models.IntegerField()
        author_detail = models.OneToOneField(to="Author_detail", to_field="aid", on_delete=models.CASCADE)
    
    

    多对多添加也是第一步也是先获取一个对象,比如作者和书籍的关系,因为author这个字段在Book表中进行多对多的表(app1_book_author)的添加,我们先获取author对象

    1. alex = models.Author.objects.filter(name="alex").first() blex = models.Author.objects.get(name="blex") alex和blex就是作者的model对象
    2. 先创建Book的id title price 以及一对多的Publish字段 bk = models.Book.objects.create(title="java",price=29,publish_id=2) #书名叫Java的对象
    3. 通过Book下的author字段添加多对多关系,通过add()方法添加,可以加对象,也可以直接加id号,也可以用列表形式,除了添加还有remove方法和all()方法可以删除和查询多对多关系
        bk.author.add(alex,blex) #利用book类下的author字段,这个字段就是获取了manytomany的对象
        bk.author.add(1,2)
        bk.author.add(*[alex,blex])   
    

    orm多对多表之更改记录操作

    比如还是作者和书籍的多对多关系,第一步还是先获取筛选对象 bk = models.Book.objects.create(title="java", price=28.23, publish=pub)
    然后有2种方法

    第一种方法
    bk.author.clear() 先清除他们的关系
    bk.author.add(3,4)在按照上面新增一个关系
    
    第二种方法用set(list) set会在新增之前把原先关系删除,而且里面默认放的就是列表,也不用加*
    bk.author.set([3,4])
    

    ORM的注意事项

    • nid = models.AutoField(primary_key=True) ID字段是自动添加的,需要自定义变量名可以自己填写.
    • 对于外键字段,Django会在字段名上添加_id来创建数据库中的别名
    • 外链字段Foreignkey有一个null=true的设置,它允许外链接受空值null,可以给赋空值None.

    多表关系的操作概要

    • 1对1的关系在两张表任意一张建立关联字段并且加Unique,比如
    作者表 author
     id  name  age
      1  alex  18
      2  blex  30
      3  clex  25
    
    作者个人信息表 authordetail
      id  addr  gender  tel  author_id(Unique)
      1    北京  男      123     1
      2    南京  女      1234    2
      3    上海  人妖    3311    3
    
    create table authordetail(
      id int primary key auto_increment,
      addr varchar(20),
      gender enum("male","female"),
      tel int(11)
      author_id int unique,
    
    );
    
    
    • 1对多的关系 需要在多个关系的表中建立关联字段
    出版社 publish
     id  name      book
      1  北京出版社  18
      2  南京出版社  30
      3  天津出版社  25
    
    create table publish(
      id int primary key auto_increment,
      name varchar(20)
    );
    
    
    书籍  book  在书籍和出版社对应关系中,一个出版社会出版多本书籍,因此把多个出版社id放在book表中创建一对多的关系,并且==要建立约束==,创建关系是为了查询,创建约束是为了防止产生脏数据
      id bookname  price  publish_id
      1  python      10        1
      2  java        20        1
      3  go          58        2
      4  php         79        3
     
    create table book(
      id int primary key auto_increment,
      bookname varchar(20),
      price    decimal(8,2),
      publish_id int,
      foreign key(publish_id) reference book(id),
    
    
    );
    
    • 多对多的关系 创建第三张关系表
    书籍 book
     id  name      price    publish_id
      1  python      18          1
      2  java        30          1
      3  go          25          2
    
    create table book(
      id int primary key auto_increment,
      name varchar(32),
      price decimal(5,2),
      publish_id int,
      foreign key (publish_id) reference publish(id),
    );
    
    
    作者表 author
     id  name  age
      1  alex  18
      2  blex  30
      3  clex  25
    
    create table author(
      id int primary key auto_increment,
      name varchar(32),
      age int,
    );
    
    做着书籍关系表 book2auther
    
      id  book_id  author_id
      1      1        1
      2      1        2
      3      2        1
      4      3        2
    create table book2auther(
      id int primary key auto_increment,
      book_id int,
      author_id int,
      foreign key (book_id) reference book(id),
      foreign key (author_id) reference author(id),
    );
    
    
    
    create table publish(
      id int primary key auto_increment,
      name varchar(20)
    );
    
    

    那么上面的sql语句在ORM中是怎么创建的呢,下面拿着SQL语法 举例在ORM中的语法

    1. 出版社和书本的一对多关系


    on_delete有6个可选值,分别是:
    CASCADE 删除级联,当父表的记录删除时,子表中与其相关联的记录也会删除。即:当一个老师被删除时,关联该老师的学生也会被删除。
    PROTECT 子表记录所关联的父表记录被删除时,会报ProtectedError异常。即:当一个学生所关联的老师被删除时,会报ProtectedError异常。
    SET_NULL 子表记录所关联的父表记录被删除时,将子表记录中的关联字段设为NULL,注意:需要允许数据表的该字段为NULL。
    SET_DEFAULT 子表记录所关联的父表记录被删除时,将子表记录中的关联字段设为一个给定的默认值。
    DO_NOTHING 子表记录所关联的父表记录被删除时,什么也不做。
    SET() 设置为一个传递给SET()的值或者一个回调函数的返回值,该参数用得相对较少。

    2. 作者和作者详情的一对一关系

    3. 书本和作者多对多的关系


    我们可以看下手动创建的Book2Author 和ManyToMany创建的 book_author表,实现的效果是一样的.

    orm一对多表之添加记录操作

    class Publish(models.Model):
        nid = models.AutoField(primary_key=True)
        publish = models.CharField(max_length=32)
        def __str__(self):
            return self.publish
    
    class book(models.Model):
        id = models.AutoField(primary_key=True)
        title = models.CharField(max_length=20)
        price = models.DecimalField(max_digits=8, decimal_places=2)
        pub_date = models.DateField()
        publish = models.ForeignKey(to="Publish", to_field="nid",on_delete=models.CASCADE)
    

    出版社和图书的对应关系为 一个出版社对应多本书,把对应关系写在book类中
    出版社数据添加不多说,因为很简单,pub = models.Publish.objects.create(publish="南京出版社")
    图书中的添加语法有2种,因为book中的publish在数据库中会自动进行字符串拼接为publish_id

    • 第一种book = models.book.objects.create(title="c++",price=18,pub_date = "2012-05-07",publish_id=2) publish_id直接写死
    • 第二种如下,此时book.title是java,book.price是28,但是book.publish 其实就是pub这个对象了,他包含了出版社的信息,所以book.publish.publish就是出版社的名字(南京出版社)
    pub = models.Publish.objects.filter(publish="南京出版社").first()  #先对Publish表进行筛选出南京出版社的对象,再把这个对象放到publish的参数中去,等同于publish_id=南京的id
    book = models.book.objects.create(title="java",price=28,pub_date = "2014-05-07",publish=pub)
    

    orm多对多表之添加记录操作

    class Book(models.Model):
        id = models.AutoField(primary_key=True)
        title = models.CharField(max_length=32)
        price = models.DecimalField(max_digits=8, decimal_places=2)
        publish = models.ForeignKey(to="Publish", to_field="pid", on_delete=models.CASCADE)
        author = models.ManyToManyField(to="Author")
    
    class Author(models.Model):
        aid = models.AutoField(primary_key=True)
        name = models.CharField(max_length=32)
        age = models.IntegerField()
        author_detail = models.OneToOneField(to="Author_detail", to_field="aid", on_delete=models.CASCADE)
    
    

    多对多添加也是第一步也是先获取一个对象,比如作者和书籍的关系,因为author这个字段在Book表中进行多对多的表(app1_book_author)的添加,我们先获取author对象

    1. alex = models.Author.objects.filter(name="alex").first() blex = models.Author.objects.get(name="blex") alex和blex就是作者的model对象
    2. 先创建Book的id title price 以及一对多的Publish字段 bk = models.Book.objects.create(title="java",price=29,publish_id=2) #书名叫Java的对象
    3. 通过Book下的author字段添加多对多关系,通过add()方法添加,可以加对象,也可以直接加id号,也可以用列表形式,除了添加还有remove方法和all()方法可以删除和查询多对多关系
        bk.author.add(alex,blex) #利用book类下的author字段,这个字段就是获取了manytomany的对象
        bk.author.add(1,2)
        bk.author.add(*[alex,blex])   
    

    orm一对多和多对多 基于对象跨表查询

    数据库查询有2种,一种是子查询,一个子查询作为另一个查询语句的结果,第二种是join查询,把N张表通过关联组成一张大表,然后再提取里面的数据.

    跨表查询对应的就是第一种子查询语句.跨表查询分 正向查询和反向查询.

    正向查询按字段:关联字段在A表, 通过A查B, 反向查询按表名(表名小写_set):关联字段在A表, 通过B查A

        #一对多 正向查询,查python书籍的出版社名字
        bk = models.Book.objects.get(title="python")
        print(bk.publish.name)
    
        # 一对多 反向查询,查南京出版社出版的所有书籍
        pub=models.Publish.objects.get(name="南京出版社")
        print(pub.book_set.all())  #表名_set 返回的是个queryset对象集合
    
        # 多对多 正向查询,查python书籍对应的所有作者名字
        bk = models.Book.objects.get(title="python")
        print([i.name for i in bk.author.all()])
    
        # 多对多 反向查询,查blex作者对应的所有书籍名称
        au = models.Author.objects.get(name="blex")
        print([i.title for i in au.book_set.all()])
    

    orm一对一 基于对象跨表查询

    正向查询和一对多 多对多一样,但是反向查询有点不同,因为是一对一,不会有多个结果,
    所以,结果也不会是queryset,语法也不用是小写表名_set,而是小写表名,例如 auth_detail.author.name

    # 一对一
        # 正向查询
        au = models.Author.objects.filter(name="blex").first()
        print(au.author_detail.add)
        # 反向查询
        auth_detail = models.Author_detail.objects.filter(add="鄞州区").first()
        print(auth_detail.author.name)
    

    orm 一对多和多对多查询 基于join查询

        #跨表inner join查询 都是在orm语法中就是和values方法
        bk = models.Author.objects.filter(name="alex").values("age")
        bk2 = models.Author.objects.filter(name="alex").values_list("age", "author_detail")
        print(bk)
        print(bk2)
    
        #基于双下划线的跨表查询 (join查询)  一对多.
        #方式一     正常查询按表名,不过表名语法略有不同,是表名__字段,values里面 publish__name意思是Publish表中的name字段
    
        bk3=models.Book.objects.filter(title="java").values("publish__name")
        print(bk3)
        #方式二 反向查询,通过出版社过滤book表中titile为python的对象,然后提取出版社的name字段
        bk4 = models.Publish.objects.filter(book__title="python").values("name")
        print(bk4)
    
        # 基于双下划线的跨表查询(join查询) 多对多查询 查询java书籍的所有作者和alex写的书籍
        #方式一 正向查询按字段
        bk5 = models.Book.objects.filter(title="java").values("author__name")
        print(bk5)
        # 方式二 反向查询按表名__字段 通过作者查询书名
        auth = models.Author.objects.filter(name="alex").values("book__title")
        print(auth)
    

    基于双下划线的跨表查询(join查询) 一对一查询的正向查询和反向查询语句和上述并无二样. 不做举例.

    基础双下划线的连续跨表查询(join查询)

    #连续跨表查询 ,查到城市以宁波开头的作者出版过的书籍和对应的出版社名字
        #方式一 正向查询
        #假如以book为起始对象,book关联了作者表和出版社表,但是并未直接关联作者详情的表.我们需要多表跨表查询获取对应的数据
        #author__author_detail__city__startswith 就是join了author author_detail2张表,然后根据city为宁波开头的条件过滤出来获得bk对象
        #"title","publish__name"  bk对象有titile字段,可以直接获取,但是publish需要通过bk的publish_id去对应到Publish表查询,属于正向查询,按字段查询.
        bk = models.Book.objects.filter(author__author_detail__city__startswith="宁波").values("title","publish__name")
        print(bk) #QuerySet [{'title': 'java', 'publish__name': '南京出版社'}, {'title': 'python', 'publish__name': '北京出版社'}]>
    
        #还是查到城市以宁波开头的作者出版过的书籍和对应的出版社名字,这次以author为基表进行反向查询
        # author和author_detail有正向的连接的author_detail_id字段,所以filter直接筛选,获取到author对象
        # 接下来通过author对象获取book名和出版社名,但是author对象和book是反向查询关系,通过book表的title和book表下publish字段关联的Publish的name字段获取到最终结果.
        auth=models.Author.objects.filter(author_detail__city__startswith="宁波").values("book__title","book__publish__name")
        print(auth)
    
  • 相关阅读:
    Git修改用户名和提交的邮箱
    在vue项目中引入bootstrap
    自定义radio,使用图片进行切换(点击切换时,获取变量值)
    nodejs知识清单
    swoft源码研究
    Nginx变量查询
    mongodb索引
    mongodb数据备份:导入导出
    mongodb主从复制和分片
    mongodb服务安装
  • 原文地址:https://www.cnblogs.com/Young-shi/p/15143090.html
Copyright © 2011-2022 走看看