Python - Django - ORM 多对多表结构的三种方式

多对多的三种方式:

  1. ORM 自动创建第三张表
  2. 自己创建第三张表, 利用外键分别关联作者和书,关联查询比较麻烦,因为没办法使用 ORM 提供的便利方法
  3. 自己创建第三张表,使用 ORM 的 ManyToManyFiled(),使用此种方式创建多对多表的时候,没有 add() remove() 等方法

 

适用方法:

  • 如果第三张表没有额外的字段,就用第一种
  • 如果第三张表有额外的字段,就用第三种或第一种

 

方法二:

models.py:

from django.db import models


# 书
class Book(models.Model):
    title = models.CharField(max_length=32)
    publish_date = models.DateField(auto_now_add=True)
    price = models.DecimalField(max_digits=5, decimal_places=2)

    def __str__(self):
        return self.title


# 作者
class Author(models.Model):
    name = models.CharField(max_length=32)
    age = models.IntegerField()

    def __str__(self):
        return self.name


# 手动创建作者和书籍关联的第三张表
# 此时在 ORM 层面,作者和书籍就没有多对多的关系了
class Author2Book(models.Model):
    id = models.AutoField(primary_key=True)
    author = models.ForeignKey(to="Author")  # 作者 id
    book = models.ForeignKey(to="Book")      # 书籍 id

在数据库中添加数据

author 表:

book 表:

author2book 表:

 

多对多的操作:

orm.py:

import os

if __name__ == '__main__':
    # 加载 Django 项目的配置信息
    os.environ.setdefault("DJANGO_SETTINGS_MODULE", "mysite2.settings")
    # 导入 Django,并启动 Django 项目
    import django
    django.setup()

    from app02 import models
    # 多对多的查询
    # 查询 id 是 2 的作者关联的书籍的 id
    ret = models.Author2Book.objects.filter(author_id=2).values_list("book_id")
    print(ret)
    
    ret = [i[0] for i in ret]  # 得到关联的书籍的 id
    # 通过书籍的 id 查询 id 是 2 的作者关联的书籍名
    ret = models.Book.objects.filter(id__in=ret)
    print(ret)

运行结果:

这里的 [i[0] for i in ret] 是为了取元组中的 id:2、3,然后通过 id:2、3 获取它们的书籍

 

方法三:

models.py:

from django.db import models

# Create your models here.


# 书
class Book(models.Model):
    title = models.CharField(max_length=32)
    publish_date = models.DateField(auto_now_add=True)
    price = models.DecimalField(max_digits=5, decimal_places=2)

    def __str__(self):
        return self.title


# 作者
class Author(models.Model):
    name = models.CharField(max_length=32)
    age = models.IntegerField()
    # 通过 through,through_fields 来指定使用创建的第三张表来构建多对多的关系
    books = models.ManyToManyField(to="Book", through="Author2Book", through_fields=("author", "book",))

    def __str__(self):
        return self.name


# 手动创建作者和书籍关联的第三张表
class Author2Book(models.Model):
    id = models.AutoField(primary_key=True)
    author = models.ForeignKey(to="Author")  # 作者id
    book = models.ForeignKey(to="Book")  # 书籍 id

    class Meta:
        unique_together = ("author", "book")  # 建立唯一约束

在数据库中添加与 app02 一样的数据

多对多的操作

orm.py:

import os

if __name__ == '__main__':
    # 加载 Django 项目的配置信息
    os.environ.setdefault("DJANGO_SETTINGS_MODULE", "mysite2.settings")
    # 导入 Django,并启动 Django 项目
    import django
    django.setup()

    from app03 import models

    ret = models.Author.objects.get(id=2).books.all()  # 获取 id 为 2 的作者关联的所有书籍
    print(ret)

运行结果:

该方法中没有 remove() 方法,可以使用下面的方法:

models.Author2Book.objects.get(author_id=1, book_id=1).delete()

 没有 django ORM 封装的那些快捷方法,我们要自己手动修改第三张表

posted @ 2019-08-07 17:51  Sch01aR#  阅读(548)  评论(0编辑  收藏  举报