多对多关联与中介模型

目录

多对多关联与中介模型

一 多对多关联的三种方式

# 多对多关联关系的建立有三种方式。

1 方式一:自行创建第三张表

class Author(models.Model):
    nid = models.AutoField(primary_key=True)
    name = models.CharField(max_length=32)
    age = models.IntegerField()

class Book(models.Model):
    nid = models.AutoField(primary_key=True)
    name = models.CharField(max_length=32)
    price = models.DecimalField(max_digits=5, decimal_places=2)
    publish_date = models.DateField()

# 自己创建第三张表,分别通过外键关联书和作者
class AuthorToBook(models.Model):
    nid = models.AutoField(primary_key=True)
    # 只需要在中间表建立外键关系即可,此表对book和author表不堵车‘一对多’关系中多的一方
    book_id = models.ForeignKey(to=Book, to_field='nid', on_delete=models.CASCADE)
    author_id = models.ForeignKey(to=Author, to_field='nid', on_delete=models.CASCADE)
    date=models.DecimalField()
    class Meta:
        unique_together = ("author", "book")

2 方式二:通过ManyToManyField自动创建第三张表

class Author(models.Model):
    nid = models.AutoField(primary_key=True)
    name = models.CharField(max_length=32)
    age = models.IntegerField()
    
# 通过ORM自带的ManyToManyField自动创建第三张表
class Book(models.Model):
    nid = models.AutoField(primary_key=True)
    name = models.CharField(max_length=32)
    price = models.DecimalField(max_digits=5, decimal_places=2)
    publish_date = models.DateField()
    # 通过ORM自带的ManyToManyField自动创建第三张表
    authors=models.ManyToManyField(to='Author')
    def __str__(self):
        return self.name

3 方式三:使用中介模型(自定义中间表)

# 设置ManyTomanyField并指定自行创建的第三张表
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'):s
    # 其中field1是定义ManyToManyField的模型外键的名(author),field2是关联目标模型(book)的外键名。

class Author2Book(models.Model):
    author = models.ForeignKey(to="Author")  # 默认的关联字段是id
    book = models.ForeignKey(to="Book")

    class Meta:
        unique_together = ("author", "book")

二 中介模型

1 多对多关系中,第三张表的建立
	-默认使用ManyToMany,自动创建
    -使用中介模型
    	-既手动创建第三张表,又可以使用方便的查询
    -完全自己写第三张表
    
# 使用中介模型

class Author(models.Model):
    nid = models.AutoField(primary_key=True)
    name = models.CharField(max_length=32)
    age = models.IntegerField()
    author_detail = models.OneToOneField(to='AuthorDatail', to_field='nid', unique=True, on_delete=models.CASCADE)


class AuthorDatail(models.Model):
    nid = models.AutoField(primary_key=True)
    telephone = models.BigIntegerField()
    birthday = models.DateField()
    addr = models.CharField(max_length=64)


class Book(models.Model):
    nid = models.AutoField(primary_key=True)
    name = models.CharField(max_length=32)
    price = models.DecimalField(max_digits=5, decimal_places=2)
    publish_date = models.DateField()

    publish = models.ForeignKey(to='Publish', to_field='nid', on_delete=models.CASCADE)
    # 当前在哪个表中,元组中的第一个参数就是 表明_id
    authors=models.ManyToManyField(to='Author',through='AuthorToBook',through_fields=('book_id','author_id'))
    def __str__(self):
        return self.name


class Publish(models.Model):
    nid = models.AutoField(primary_key=True)
    name = models.CharField(max_length=32)
    city = models.CharField(max_length=32)
    email = models.EmailField()

class AuthorToBook(models.Model):
    nid = models.AutoField(primary_key=True)
    book_id = models.ForeignKey(to=Book, to_field='nid', on_delete=models.CASCADE)
    author_id = models.ForeignKey(to=Author, to_field='nid', on_delete=models.CASCADE)
    date=models.DecimalField()  # 【不能用add ,remove, clear, set等操作的原因,可能会有新的字段加入,导致数据错误】
    
# 使用中介模型后的方法变化:

# 脚本文件s1.py  
import os

if __name__ == '__main__':
    os.environ.setdefault("DJANGO_SETTINGS_MODULE", "day76.settings")
    import django
    django.setup()
    from app01 import models
    ## (a)不使用中介模型的测试:
    # 东游记这本书是lqz和egon写的
    # book=models.Book.objects.get(pk=1)
    # # book.authors.add(1,2) # 自己创建第三张表,不做关联,用不了了
    # # 只能手动写
    # models.AuthorToBook.objects.create(book_id_id=1,author_id_id=1)  # 【写book_id_id的原因:book_id是字段对象,建表的时候,自动加了_id】
    # models.AuthorToBook.objects.create(book_id_id=1,author_id_id=2)

    # 东游记这本书所有的作者:原生写法,不方便
    # book = models.Book.objects.get(pk=1)
    # res=models.AuthorToBook.objects.filter(book_id=book)  ### 【另一种写法:book_id_id = book.nid】
    # print(res)

    ## (b)使用了中介模型之后: 
    # book = models.Book.objects.get(pk=1)
    # print(book.authors.all())
    	
    # 东游记这本书是lqz和egon写的 add ,remove, clear, set
    # 但是连表操作,book.authors这些都能用
    book = models.Book.objects.get(pk=1)
    book.authors.add(1,2) # 不能用了
上一篇:EF简单的增删改查(两表)


下一篇:mfc对话框禁止关闭