Wagtail 站点中博客应用程序的模型关系设计

model relationship design for Blog app in Wagtail site

下面models.py在wagtail网站建博客来自this post.

class BlogPage(Page):
    description = models.CharField(max_length=255, blank=True,)

    content_panels = Page.content_panels + [FieldPanel("description", classname="full")]


class PostPage(Page):
    header_image = models.ForeignKey(
        "wagtailimages.Image",
        null=True,
        blank=True,
        on_delete=models.SET_NULL,
        related_name="+",
    )

    tags = ClusterTaggableManager(through="blog.PostPageTag", blank=True)

    content_panels = Page.content_panels + [
        ImageChooserPanel("header_image"),
        InlinePanel("categories", label="category"),
        FieldPanel("tags"),
    ]


class PostPageBlogCategory(models.Model):
    page = ParentalKey(
        "blog.PostPage", on_delete=models.CASCADE, related_name="categories"
    )
    blog_category = models.ForeignKey(
        "blog.BlogCategory", on_delete=models.CASCADE, related_name="post_pages"
    )

    panels = [
        SnippetChooserPanel("blog_category"),
    ]

    class Meta:
        unique_together = ("page", "blog_category")


@register_snippet
class BlogCategory(models.Model):
    name = models.CharField(max_length=255)
    slug = models.SlugField(unique=True, max_length=80)

    panels = [
        FieldPanel("name"),
        FieldPanel("slug"),
    ]

    def __str__(self):
        return self.name

    class Meta:
        verbose_name = "Category"
        verbose_name_plural = "Categories"


class PostPageTag(TaggedItemBase):
    content_object = ParentalKey("PostPage", related_name="post_tags")


@register_snippet
class Tag(TaggitTag):
    class Meta:
        proxy = True

我想知道,引入额外中介模型的主要原因是什么 (class PostPageBlogCategory(models.Model): & class PostPageTag(TaggedItemBase): ) 到 link PostPage 类别和标签?
为什么不直接使用 ParentalForeignkeyParentalManyToManyKey 呢?

简短的回答是 Django 的 ManyToManyField 在两端的模型尚不存在时需要如何建立关系方面有一些限制,添加 'intermediary model' 有助于解决这个问题。

更长的答案

与软件中的任何事物一样,有多种方法可以做某事,每种方法各有利弊。 Django 的内置字段很简单,可以让您做很多强大的事情来表示关系数据,但这种简单性会降低管理这些关系的灵活性。

Wagtail CMS 管理界面的主要目标之一是能够像在实际单击 'save' 之前创建数据(包括关系)一样工作。虽然乍一看这似乎很简单,但一旦您开始考虑关系数据,要做到这一点就需要一些细微差别。

  • Wagtail 内置了一个名为 django-modelcluster 的非常强大的库,该库专为许多您希望使用关系数据而无需首先在数据库中存储所有位的情况而构建。
  • 每个 Wagtail Page 实际上继承了 modelcluster.models.ClusterableModel,这就是为什么博客 post 中的某些功能似乎在编辑器中有效,即使数据库条目还没有尚未保存。
  • 关于 blog post you linked, there is a section towards the end with the heading 'ParentalKey' 进一步解释了这种细微差别以及仅使用 Django 的基本方法如何有一些缺点。
  • Django docs for many-to-many relationships 上,通读并注意每个单独的模型实例必须首先在数据库中,然后才能 'link' 这两个实例分别进行第二次更新。