zoukankan      html  css  js  c++  java
  • Day64 django--ORM2

    一,ORM表和表之间的关系字段

      1.一对一:OneToOneField,

        通常一对一字段用来扩展已有的字段

        Q:为什么要有OneToOneField?

          1.当一张表里的字段非常多,并且某几个字段的查询频率远远大于其他字段的时候

          2.把常用字段单独拆成一张表,查询的时候更快捷

    #示例:作者信息扩展
    class Author(models.Model):
        name = models.CharField(max_length=32)
        info = models.OneToOneField(to='AuthorInfo')
        
    
    class AuthorInfo(models.Model):
        phone = models.CharField(max_length=11)
        email = models.EmailField()
     
    #OneToOneField字段参数
    to     #设置要关联的表
    to_field     #设置要关联的字段
    on_delete   #当删除关联表中的数据是,当前表其关联的行的行为,用法同ForeignKey字段

      2.一对多:外键(ForeignKey)

        外键类型在ORM中用来表示外键关联关系,一般把ForeignKey字段设置在'一对多'中‘多’的一方

        ForeignKey可以和其他表做关联关系同时也可以和自身做关联关系

    #ForeignKey字段参数
    
    to   #设置要关联的表
    
    to_field  #设置高关联的表的字段
    
    related_name  #反向操作时,使用的字段名,用于代替原反向查询时的'表名_set'
    
        #例如:
        class Classes(models.Model):
            name = models.CharField(max_length=32)
    
        class Student(models.Model):
            name = models.CharField(max_length=32)
            theclass = models.ForeignKey(to="Classes")
    
        #当我们要查询某个班级关联的所有学生(反向查询)
        Classes.objects.first().student_set.all()
    
        #当我们在ForeignKey字段中添加了参数 related_name 后
        class Student(models.Model):
            name = models.CharField(max_length=32)
            theclass = models.ForeignKey(to="Classes", related_name="students")
    
        #然后,当我们要查询某个班级关联的所有学生(反向查询)
        Classes.objects.first().students.all()
    
    related_query_name  #反向查询操作时,使用的连接前缀,用于替换表名
    
    on_delete  #当删除关联表中的数据时,当前表与其关联的行的行为
        on_delete=models.CASCADE  #删除关联数据,与之关联也删除
        on_delete=models.DO_NOTHING  #删除关联数据,引发错误IntegrityError
        on_delete=models.PROTECT  #删除关联数据,引发错误ProtectedError
        on_delete=models.SET_NULL  #删除关联数据,与之关联的值设置为null(前提FK字段需要设置为可空)
        on_delete=models.SET_DEFAULT  #删除关联数据,与之关联的值设置为默认值(前提FK字段需要设置默认值)
        on_delete=models.SET  #删除关联数据,
            a.与之关联的值设置为指定值,设置:models.SET(值)
            b.与之关联的值设置为可执行对象的返回值,设置:models.SET(可执行对象)
                def func():
                    return 10
    
                class MyModel(models.Model):
                    user = models.ForeignKey(
                        to="User",
                        to_field="id",
                        on_delete=models.SET(func)
                )
    
    db_constraint  #是否在数据库中创建外键约束,默认为True
    
            

      3.多对多:另外一种关系表(ManyToManyField)

        用于表示多对多的关联关系。在数据库中通过第三张表来建立关联关系

    #ManyToManyField字段参数
    
    to  #设置要关联的表
    
    related_name  #反向操作时,使用的字段名,用于代替原反向查询时的'表名_set',用法同ForeignKey字段
    
    related_query_name  #反向查询操作时,使用的连接前缀,用于替换表名,用法同ForeignKey字段
    
    symmetrical  #仅用于多对多自关联时,指定内部是否创建反向操作的字段,默认为True
    
        #例:
        #此时,person对象就没有person_set属性
        class Person(models.Model):
            name = models.CharField(max_length=16)
            friends = models.ManyToManyField("self")
    
        #此时,person对象现在就可以使用person_set属性进行反向查询
        class Person(models.Model):
            name = models.CharField(max_length=16)
            friends = models.ManyToManyField("self", symmetrical=False)    
    
    through  #在使用ManyToManyField字段时,Django将自动生成一张表来管理多对多的关联关系。但我们也可以手动创建第三张表来管理多对多关系,此时就需要通过through来指定第三张表的表名
     
    through_fields  #通过through_fields来指定第三张表的关联的字段
    
    db_table  #默认创建第三张表时,数据库中表的名称

        多对多关联关系的三种方式

          1.自己创建第三张关系表,外键分别关联两个表

            优点:可以扩充第三张关系表的字段

            缺点:自己做连表查询

    class Book(models.Model):
        title = models.CharField(max_length=32, verbose_name="书名")
    
    
    class Author(models.Model):
        name = models.CharField(max_length=32, verbose_name="作者姓名")
    
    
    # 自己创建第三张表,分别通过外键关联书和作者
    class Author2Book(models.Model):
        author = models.ForeignKey(to="Author")
        book = models.ForeignKey(to="Book")
        
        #设置这两个字段联合唯一
        class Meta:
            unique_together = ("author", "book")

          2.通过ORM内置的ManyToManyField,自动创建第三张关系表

            优点:提供了很多连表操作的快捷方法:all(),add(),set(),clear(),remove()

            缺点:无法扩展第三张关系表

    class Book(models.Model):
        title = models.CharField(max_length=32, verbose_name="书名")
    
    
    # 通过ORM自带的ManyToManyField自动创建第三张表
    class Author(models.Model):
        name = models.CharField(max_length=32, verbose_name="作者姓名")
        books = models.ManyToManyField(to="Book", related_name="authors"

          3.自己创建第三张关系表,通过ManyToManyField

            优点:既能够使用多对多查询的快捷方法all(),还能够自己扩展第三张关系表的字段

        

    class Book(models.Model):
        title = models.CharField(max_length=32, verbose_name="书名")
    
    
    # 自己创建第三张表,并通过ManyToManyField指定关联
    class Author(models.Model):
        name = models.CharField(max_length=32, verbose_name="作者姓名")
        books = models.ManyToManyField(to="Book", through="Author2Book", through_fields=("author", "book"))
        # through_fields接受一个2元组('field1','field2'):
        # 其中field1是定义ManyToManyField的模型外键的名(author),field2是关联目标模型(book)的外键名。
    
    
    class Author2Book(models.Model):
        author = models.ForeignKey(to="Author")
        book = models.ForeignKey(to="Book")
        
        #设置这两个字段联合唯一
        class Meta:
            unique_together = ("author", "book")

        Q.以后该用哪种?

          1.当第三张关系表中不需要其他额外字段的时候,我们就用默认的ManyToManyField就可以了

          2.当第三张关系表中需要额外的字段时,我们就要用第三种方式,自己建立第三张关系表并使用ManyToManyField

    二,ORM关联查询

      1.基于对象的查询(跨表)

        1.正向查询

          语法:对象.关联字段.字段

    #示例:
    book_obj = models.Book.objects.first()  # 第一本书对象
    print(book_obj.publisher)  # 得到这本书关联的出版社对象
    print(book_obj.publisher.name)  # 得到出版社对象的名称

        2.反向查询

          语法:obj.表名_set

          1.默认不设置related_name属性

            1.查找的对象是多个的时候(一对多或多对多时)

              语法:publisher_obj.book_set.all()

            2.查找的对象是一个的时候(一对一)

              语法:author_info_obj.author.name

          2.设置related_name='books'属性

            publisher_obj.books.all()

    #示例
    publisher_obj = models.Publisher.objects.first()  # 找到第一个出版社对象
    books = publisher_obj.book_set.all()  # 找到第一个出版社出版的所有书
    titles = books.values_list("title")  # 找到第一个出版社出版的所有书的书名

      2.基于QuerySet的查询

        1.正向查询

          语法:关联字段__字段

    #示例
    Book.objects.filter(id=1).values_list('publisher_name')
    Book.objects.values_list("publisher__name")  #查询全部的时候all()可省略

        2.反向查询

          语法:表名__字段

          1.默认不设置related_name属性,默认就用类名的小写

            Publisher.objects.filter(id=1).values_list('book_price')

          2.设置related_name='book'属性

            Publisher.objects.filter(id=1).values_list('books_price')

    titles = Publisher.objects.values_list("book__title")
  • 相关阅读:
    数组的地址和vector数组的地址
    字节跳动 测试开发工程师 面经
    最短路径树
    SPFA
    树的直径
    树的重心
    CF1401D Maximum Distributed Tree
    期望简述
    CF723E One-Way Reform
    CF1409E Two Platforms
  • 原文地址:https://www.cnblogs.com/lianyeah/p/9932013.html
Copyright © 2011-2022 走看看