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")
原文地址:https://www.cnblogs.com/lianyeah/p/9932013.html