Django / Wagtail 中的大型嵌套层次结构:育儿还是分类?

Large nested hierarchy in Django / Wagtail: parenting or categorizing?

我有一个数据库,其中包含 50,000 种药物(药物)的元数据,这些药物按层次排序(分类法称为 ATC)。心脏药物的例子如下:

有些药物有 4 个级别。

我需要为每种药物生成一个单独的页面。在 wagtail/django 中执行此操作的最有效方法是什么,包括考虑到用户需要一种简单直观的方法来搜索数据库。

我试过 django-mptt,定义了以下模型。

class ATCChapter(MPTTModel): # MAIN CHAPTER
    chapter_letter = models.CharField(max_length=255, null=True, blank=True) # E.g "A"
    chapter_title = models.CharField(max_length=255, null=True, blank=True) # E.g "Cardiac drugs"
    parent = TreeForeignKey('self', on_delete=models.CASCADE, null=True, blank=True, related_name='children')

    class MPTTMeta:
        order_insertion_by = ['chapter_letter']

class ATCSubchapter(MPTTModel): # SUBCHAPTER
    subchapter_letter = models.CharField(max_length=255, null=True, blank=True) # E.g "A10"
    subchapter_title = models.CharField(max_length=255, null=True, blank=True) # E.g "Drugs used in heart failure"
    parent = TreeForeignKey(ATCChapter, on_delete=models.CASCADE, null=True, blank=True, related_name='subchapter')

    class MPTTMeta:
        order_insertion_by = ['subchapter_letter']

class ATCDrug(MPTTModel, Page): # INDIVIDUAL DRUG
    drug_code = models.CharField(max_length=255, null=True, blank=True) # E.g "A10X"
    drug_name = models.CharField(max_length=255, null=True, blank=True) # E.g "Metoprolol"
    parent = TreeForeignKey(ATCSubchapter, on_delete=models.CASCADE, null=True, blank=True, related_name='disease')

    class MPTTMeta:
        order_insertion_by = ['drug_code']

进行迁移会引发以下错误:class ATCDrug(MPTTModel, Page): TypeError: metaclass conflict: the metaclass of a derived class must be a (non-strict) subclass of the metaclasses of all its bases

这可以通过不让 class 从 Page 继承来解决,这当然很糟糕。我删除了 Page 并尝试了模型,但无法验证亲子方案是否正确。

问题:鉴于目标,我是否在做一些明显错误或次优的事情。

系统:Wagtail 2.10,Postgresql,计划使用Algolia进行搜索

感谢任何建议。

根据您要求每种药物都用一个页面表示,如果您打算中长期使用 Wagtail,我建议每种药物都使用页面模型。

这是因为您将获得能够向用户展示此内容的所有好处,提供搜索、API 和 UI 编辑功能而不会遇到任何麻烦。

但是,下一个决定是将所有这些都放在一个父页面模型下,还是将层次结构存储在页面模型中。

如果您知道层次结构在恰好五个深度级别上会非常严格,并且每个深度都有特定的名称和商定的定义,那么最好将这些 'levels' 代码化到模型中还。请注意,每个药物页面的 url 将默认为 url.com/level-1/level2-/..../insulin 而不是 url.com/medications/insulin.

之类的内容

但是,通过 RoutablePageMixin 也可以很容易地使每个药物在 Url 树中的某个固定 (non-nested) 点可用。但是,如果您希望规范 URL 成为此 non-nested 变体,您可能会发现自己与 Wagtail 进行了少量斗争。这样做的好处是,您只需通过内置的页面浏览器(管理菜单)导航,就可以在树中的正确位置找到胰岛素页面。

换句话说,将层次结构存储为页面模型仍然值得,但药物页面模型本身将是其他中央页面的子级。这为每种药物提供了更简单的规范 URLs,但也意味着每个级别的页面都可以使用 RoutablePageMixin 来访问其后代子项。这种方法的缺点是管理编辑界面不会直接反映与药物页面相关的层次结构。

但是,在 50,000 个条目下,编辑交互将需要一些调整和替代方法才能找到页面。

例如

  • ...关卡
  • ...... A1(等)
  • ...药物
  • ...... 胰岛素
  • 联系方式(其他杂项页面也会在主页下)

这里可能没有 'right' 答案,您可能会发现最好设置一些程序化的页面创建和链接(或类似于固定装置的东西),然后两种方式都做并设置您的 beta Wagtail 实例中的两个站点。通过这种方式,您可以看到编辑的感觉,让您的团队有机会参加比赛并设置 API。最后,无论哪种方式,您最终都需要在页面模板和模型方面非常相似的代码。