繁体   English   中英

Django抽象与非抽象模型继承

[英]Django absract vs non-abstract model inheritance

考虑这两个模型类BookArticle

class Book(models.Model):
    title = models.CharField(max_length=100)


class Article(models.Model):
    title = models.CharField(max_length=100)

想象一下这种情况:一本书可以有很多注释,但是注释只能引用一本书。 文章也是一样。 我已经开发了两种解决方案:

非抽象解决方案

class Annotation(models.Model):
    body = models.TextField()
    article = models.ForeignKey(Article, blank=True)
    book = models.ForeignKey(Book, blank=True)

    class Meta:
        default_related_name = 'annotations'

优点

  • 代码是DRY
  • 可以使用book.annotationsarticle.annotations访问注释

缺点

  • 浪费数据库内存(两个字段articlebook必须为none)

抽象类解决方案

class Annotation(models.Model):
    body = models.TextField()

    class Meta:
        abstract = True


class BookAnnotation(Annotation):
    book = models.ForeignKey(Book, blank=True)

    class Meta:
        default_related_name = 'book_annotations'


class ArticleAnnotation(Annotation):
    article = models.ForeignKey(Article, blank=True)

    class Meta:
        default_related_name = 'article_annotations'

优点

  • 明确区分书籍和文章注释
  • 没有内存浪费

缺点

  • 与注释的概念不太匹配(对象类型应该相同)
  • 可以使用book.book_annotationsarticle.article_annotations访问注释(不是很丑吗?)。 我不能将annotations用作相关名称,因为Django禁止这样做,它说reverse query name for BookAnnotation clashes with field name ArticleAnnotation

处理这种情况的最佳方法是哪种?

您可以在这里考虑一般关系

class Annotation(models.Model):
    body = models.TextField()
    content_type = models.ForeignKey(ContentType, on_delete=models.CASCADE)
    object_id = models.PositiveIntegerField()
    annotated_object = GenericForeignKey('content_type', 'object_id')

class Book(models.Model):
    ...
    annotations = GenericRelation('Annotation')

class Article(models.Model):
    ...
    annotations = GenericRelation('Annotation')

现在,您可以将annotation.annotated_object obj.annotations设置为任何书籍或文章实例,相反,可以同时对书籍和文章对象进行obj.annotations

暂无
暂无

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM