通过多对多模型继承

时间:2019-02-27 06:00:14

标签: django django-models

假设我有以下模型:

class Author(Model):
    name = CharField()

class Publication(Model):
    name = CharField()
    authors = ManyToManyField(Author)
    class Meta:
        abstract = True
class Book(Publication):
    pass
class Article(Publication):
    pass
class Journal(Publication):
    pass

如何更改代码,以便可以将through表添加到authors?如果我写authors = ManyToManyField(Author, through='Relationship'),它将不起作用。

1 个答案:

答案 0 :(得分:-1)

值得庆幸的是,Django无需任何编码即可处理中间表。您甚至可以使用M2M关系管理器上的.through访问它们,例如one_publication.authors.through

如果您要自己管理贯通表,只需指定它即可。因为您要添加的字段不仅仅是两个相关实体的外键。是这样吗?

如果是,则必须创建一个Relationship模型(考虑提供一个更有用的名称),其中包含指向PublicationAuthor的外键。

更新:如果要向多对多关系中的对象列表添加默认顺序,则中间模型确实是实现此目的的一种方法:

class Relationship(models.Model):
    author = models.ForeignKey(Author)
    publication = models.ForeignKey(Publication)
    # Any further fields that you need

    class Meta:
        ordering = ['author__last_name', 'author__first_name']

但是,您可以在查询m2m关系时轻松地对其进行排序,而无需任何中间模型或通过管理器:

book = Book.objects.first()
for author in book.authors.order_by('last_name', 'first_name'):
    # Will print in alphabetical order
    print(f'Author: {author.first_name} {author.last_name}')

一个警告是,如果使用预取,则需要在Prefetch对象中指定顺序,以避免执行两次查询,首先是不带顺序的预取,而不是带顺序的访问。

# 2 queries plus one for every book
books = Book.objects.prefetch_related('authors')
for book in books:
    for author in book.authors.order_by('last_name', 'first_name'):
        print(f'Author: {author.first_name} {author.last_name}')

# 2 queries regardless of number of books
books = Book.objects.prefetch_related(Prefetch('authors',
    queryset=Author.objects.order_by('last_name', 'first_name')))
for book in books:
    for author in book.authors.all():
        print(f'Author: {author.first_name} {author.last_name}')