ORM關於表那些事

複製代碼
1、. ORM表和表之間的關係
    一、 一對多           --> 外鍵(ForeignKey)
    
    二、 多對多           --> 另一張關係表(ManyToManyField)
        1. 三種方式 1. 本身創建第三張關係表,外鍵分別關聯兩個表
                1. 優勢
                    1. 能夠擴充第三張關係標的字段
                2. 缺點
                    1. 本身作連表查詢
                3. 建表例子
                    class Book(models.Model):
                        title = models.CharField(max_length=12)


                    class Author(models.Model):
                        name = models.CharField(max_length=12)


                    # 1. 多對多第一種建立方式:本身建立第三張關係表
                    class Author2Book(models.Model):
                        id = models.AutoField(primary_key=True)
                        author_id = models.ForeignKey(to='Author')
                        book_id = models.ForeignKey(to='Book')
                        price = models.IntegerField()  # 能夠本身擴充須要的字段

            2. 經過ORM內置的ManyToManyField,自動建立第三張關係表
                1. 優勢
                    1. 提供了不少連表操做的快捷方法--> all(), add(), set(), clear(), remove()
                2. 缺點
                    1. 沒法擴展第三張關係表
                3. 建表例子
                    class Book(models.Model):
                        title = models.CharField(max_length=12)


                    class Author(models.Model):
                        name = models.CharField(max_length=12)
                        books = models.ManyToManyField(to='Book')  # 字段就這些,沒法擴充其餘字段
            
            3. 本身建立第三張關係表,經過ManyToManyField關聯
                1. 優勢:
                    1. 既可以使用多對多查詢的快捷方法all()(只能用all,不能使用add,set等),還可以本身擴展第三張關係表的字段
                2. 建表例子
                    class Book(models.Model):
                        title = models.CharField(max_length=12)


                    class Author(models.Model):
                        name = models.CharField(max_length=12)
                        # 告訴ManyToManyField經過(through)Author2Book這張表進行關聯,不使用ORM自動建立的第三張表,而是使用我本身建立的表
                        # through_fields告訴ORM經過哪幾個字段進行多對多關聯
                        books = models.ManyToManyField(to='Book', through='Author2Book', through_fields=('author', 'book'))


                    # 1. 多對多第三種建立方式:本身建立第三張關係表,此時外鍵不須要添加_id了,由於ORM會默認幫你在外鍵後面加_id
                    class Author2Book(models.Model):
                        id = models.AutoField(primary_key=True)
                        author = models.ForeignKey(to='Author')
                        book = models.ForeignKey(to='Book')
                        price = models.IntegerField(null=True)

                        # author_id和book_id要聯合惟一
                        class Meta:
                            unique_together = (('author', 'book'),)
                    3. 操做例子
                        # 多對多的第三張方式也支持all查詢
                        author_obj = Author.objects.first()
                        # 第一個做者的全部書籍
                        ret = author_obj.books.all()

                        # 給第一個做者添加一本書
                        # author_obj.books.add(4) # 報錯
                        Author2Book.objects.create(author_id=1, book_id=4)


        2. 之後該用哪一種?
            1. 當第三張關係表中不須要其餘額外字段的時候,咱們就用默認ManyToManyField就能夠了
            2. 當第三張關係表中須要額外的字段時,咱們就要用第三種方式,本身創建第三張關係表而且用ManyToManyField關聯
        
        
    三、 一對一           --> OneToOneField    
        0. 用法和外鍵同樣
        1. 當一張表裏的字段很是多,而且某幾個字段的查詢頻率遠遠大於其餘字段的時候
        2. 把經常使用字段單獨拆成一張表,查詢的時候更快捷!
        3. 當兩張表創建了一對一關係後,就不能再關聯其餘表了
        4. 建表例子
            class Author(models.Model):
                name = models.CharField(max_length=12)  # 姓名
                gender = models.SmallIntegerField(choices=((1, ''), (2, ''), (3, '保密')), default=3)  # 性別
                phone = models.CharField(max_length=11, unique=True)  # 手機
                email = models.EmailField()  # 郵箱
                info = models.OneToOneField(to='AuthorInfo')  # 詳細信息,一對一


            # 做者詳細信息表
            class AuthorInfo(models.Model):
                birthday = models.DateTimeField()  # 生日
                city = models.CharField(max_length=12)  # 住址
                is_marry = models.BooleanField()  # 婚否
                income = models.BigIntegerField()  # 收入

        5. 查詢例子
                # 一對一查詢,查詢第一個做者的住址
                author_obj = Author.objects.first()
                ret = author_obj.info.city


2、 ORM關聯查詢

1、 基於對象的查詢
    0. 建表
        class Publisher(models.Model):
            id = models.AutoField(primary_key=True)
            name = models.CharField(max_length=20)
            addr = models.TextField()
            date = models.DateField()  # 成立日期

            def __str__(self):
                return self.name


        class Book(models.Model):
            id = models.AutoField(primary_key=True)
            title = models.CharField(max_length=20)
            price = models.DecimalField(max_digits=6, decimal_places=2)
            isbn = models.CharField(max_length=20, unique=True)  # 書籍的惟一編號
            publisher = models.ForeignKey(to='Publisher', on_delete=models.CASCADE)

            def __str__(self):
                return self.title


        class Author(models.Model):
            name = models.CharField(max_length=12)  # 姓名
            gender = models.SmallIntegerField(choices=((1, ''), (2, ''), (3, '保密')), default=3)  # 性別
            phone = models.CharField(max_length=11, unique=True)  # 手機
            email = models.EmailField()  # 郵箱
            books = models.ManyToManyField(to='Book')  # 做品
            info = models.OneToOneField(to='AuthorInfo')  # 詳細信息


        # 做者詳細信息表
        class AuthorInfo(models.Model):
            birthday = models.DateTimeField()  # 生日
            city = models.CharField(max_length=12)  # 住址
            is_marry = models.BooleanField()  # 婚否
            income = models.BigIntegerField()  # 收入
    
    1. 正向查
        對象.關聯字段.屬性
                # 查詢第一本書關聯的出版社名稱
                book_obj = Book.objects.first()
                ret = book_obj.publisher.name
                print(ret)

    2. 反向查
        1. 默認不設置related_name屬性
            1. 查找的對象是多個的時候(一對多或多對多時)
                publisher_obj.book_set.all()

            2. 查找的對象時一個的時候(一對一)
                author_info_obj.author.name

            3. 例如
                # 一對多查詢(須要給反向查詢的表加_set)
                # 查詢第一本書關聯的出版社名稱(正向查)
                book_obj = Book.objects.first()
                ret = book_obj.publisher.name
                print(ret)

                # 查詢明哥出版社出版的全部書(反向查)
                publisher_obj = Publisher.objects.get(name='明哥出版社')
                # 反向查找(多個) .表名_set
                ret = publisher_obj.book_set.all()
                print(ret)

                # 一對一查詢(不須要給反向查詢的表加_set)
                # 查詢id=1的做者婚否(正向查)
                author_obj = Author.objects.first()
                ret = author_obj.info.is_marry
                print(ret)

                # 查找住在深圳的那個做者姓名(反向查)
                authorinfo_obj = AuthorInfo.objects.get(city='深圳')
                ret = authorinfo_obj.author.name
                print(ret)


        2. 設置related_name='books'屬性(publisher = models.ForeignKey(to='Publisher', related_name='books'))
            # 查詢明哥出版社出版的全部書
            publisher_obj = Publisher.objects.get(name='明哥出版社')
            publisher_obj.books.all()

二、 基於QuerySet的查詢(__表示跨表查詢)
    1. 正向查
        Book.objects.filter(id=1).values_list('publisher__name')

    2. 反向查
        1. 默認不設置related_name屬性,默認就用類名的小寫
            Publisher.objects.filter(id=1).values_list('book__price')
        2. 設置related_name='books'屬性
            Publisher.objects.filter(id=1).values_list('books__price')
    3. related_query_name = 'hello'
        在關聯的字段參數設置了related_query_name = 'hello'後,反向查找就不須要使用表名,而是直接使用"hello"

    3. 例子
    # 熱身:普通的values的使用
    # 查詢第一本書的名稱
    ret = Book.objects.filter(id=1).values('title')
    print(ret)

    # 使用:外鍵基於QuerySet跨表查詢
    # 查詢第一本書關聯的出版社名稱(__表示跨表查詢)(正向查找)
    # valuse('publisher')表示經過外鍵找到了publisher表,__表示跨表取到publisher表的字段的值
    ret = Book.objects.filter(id=1).values('publisher__name')  
    print(ret)

    # 反向查找
    # 查詢id=1的出版社的全部書的名稱和價格
    ret = Publisher.objects.filter(id=1).values_list('book__title', 'book__price')
    print(ret)

    # 一對一基於QuerySet跨表查詢
    # 查詢id=1的做者婚否(正向查找)
    ret = Author.objects.filter(id=1).values('info__is_marry')
    print(ret)

    # 查找住在深圳的做者的姓名(反向查找)
    ret = AuthorInfo.objects.filter(city='深圳').values('author__name')
    print(ret)

     # 多對多基於QuerySet跨表查詢
    # 查詢id=1的做者關聯的全部數據的名稱和價格(正向查找)
    ret = Author.objects.filter(id=1).values('books__title', 'books__price')
    print(ret)

    # 查找id=1的做者的名字(反向查找)
    ret = Book.objects.filter(id=1).values('author__name')
    print(ret)

    # 鏈式查詢
    # 查找id=1的書的做者的城市
    ret = Book.objects.filter(id=1).values('author__info__city')
    print(ret)
複製代碼
相關文章
相關標籤/搜索