• Python


    多对多的三种方式:

    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 封装的那些快捷方法,我们要自己手动修改第三张表

  • 相关阅读:
    linux同一客户端多个git账号的配置
    linux同一台机子上用多个git 账号
    执行ssh-add时出现Could not open a connection to your authentication agent
    国内常用NTP服务器地址及IP
    PHP双引号的隐患
    mysql 累加求和
    php实现Facebook风格的 time ago函数
    Mysql之数据库设计规范
    搭建Git服务器
    win7下如何根据端口号杀掉进程
  • 原文地址:https://www.cnblogs.com/sch01ar/p/11316808.html
Copyright © 2020-2023  润新知