眼前有个二级产品分类的需求,分类数据同时要给企业详情和其他一些在线表单调用,感觉用 wagtail 的 snippets 实现比较合适。

但我发现 wagtail 手册中 snippets 部分并没有提及附加子数据的内容。我模仿 Page 模型页面附加图集的方式,初步实现了这个需求。

from django.db import models
from modelcluster.fields import ParentalKey
from modelcluster.models import ClusterableModel
from wagtail.core.models import Orderable
from wagtail.admin.edit_handlers import FieldPanel, InlinePanel
from wagtail.snippets.models import register_snippet


@register_snippet
class ProductCategory(ClusterableModel, models.Model):
    name = models.CharField('中文名', blank=False, max_length=250)
    name_en = models.CharField('English Name', blank=True, max_length=250)

    panels = [
        FieldPanel('name'),
        FieldPanel('name_en'),
        InlinePanel('child_category', label='子分类'),
    ]

    def __str__(self):
        return self.name
    

class ProductChildCategory(Orderable):
    page = ParentalKey(ProductCategory, on_delete=models.CASCADE,
                       related_name='child_category')
    name = models.CharField('中文名', blank=False, max_length=250)
    name_en = models.CharField('English Name', blank=True, max_length=250)

    panels = [
        FieldPanel('name'),
        FieldPanel('name_en'),
    ]

重点在于 ProductCategory 类要添加继承 ClusterableModel 而且要放在第一位,否则迁移时会发生错误:

SystemCheckError: System check identified some issues:

ERRORS:
company.ProductChildCategory.page: (modelcluster.E001) ParentalKey must point to a subclass of ClusterableModel.
HINT: Change company.ProductCategory into a ClusterableModel or use a ForeignKey instead.

ParentalKey 必须指向 ClusterableModel 的子类。

Reference