【发布时间】:2019-12-18 04:32:32
【问题描述】:
首先,我知道有 django-mptt 和 django-treebeard 之类的软件包,但这些看起来不像我要找的。 (目标似乎是将所有模型实例排列在一棵树中,并且模型具有对每个实例的位置进行编码的字段。只有一棵树,可以重新排列、删除或新插入节点。)
任务:
粗略地说,我的目标是拥有一个存储树木的模型。数据库中要存储多棵树,模型的每个实例都存储其中一棵树。我将尝试说明两个不同复杂度的不同用法示例。第一个可能很容易实现,第二个......我不知道。
[附带问题:我要找的东西有名字吗?搜索 django+tree 导致讨论问题和解决方案,类似于 django-mptt...]
简单案例:
考虑章节和书籍的模型。
class Chapter(Model):
heading = CharField()
text = TextField()
class Book(Model):
name = CharField()
structure = ???magic???
章节模型存储书籍的文本部分,因此您将有一个实例保存主题 A 的标题和文本,另一个实例保存主题 B,依此类推。书籍模型必须存储书籍的结构,即哪些章节去哪里。一本书有多个章节,一个章节可以出现在多本书中,例如想象两本专门针对同一主题的书籍实例,一本针对初学者,另一本针对专家。虽然这两本书共享一些章节,但它们的结构不同:
Book Beginner
1. Introduction I
2. Topic TA
3. Topic TB
4. Topic TC
Book Expert
1. Topic TA
2. Topic TB
2.1. Advanced Topic AT1
2.2. Advanced Topic AT2
2.2.1 Special Case SCX
3. Topic TC
4. Topic TD
我正在使用 Django、REST 框架和 PostgreSQL。是否存在将书籍的树结构存储在数据库字段中的现有解决方案?如果没有,有什么好的方法来解决它?
我的一个想法是使用 JSONField 并存储包含章节实例主键的嵌套数组,即[I, TA, TB, TC] 用于 book1,[TA, TB, [AT2, AT2, [SCX]], TC, TD] 用于 book2。合理与否?
复杂情况:
(这可能是我真正想要做的。有点类似于上面,但更多元;类似于书籍和章节的合理性也有点崩溃,但我还是会使用它。)
class Paragraph(Model):
text = TextField()
class ChapterTree(Model):
structure = ???magic???
headings = ???magic???
class Book(Model):
name = CharField()
chapter_structure = ForeignKey(ChapterTree)
contents = ???magic???
好的,这一次段落只是一个文本块; ChapterTree 存储章节的布局,但除了可能所有相应的章节标题之外没有文本;一本书必须使用一个预定义的章节结构,并且需要指定哪些段落应该出现在每个章节中。 (即,具有相同章节树的两本印刷书籍总是有相同的目录,但可能有不同的段落作为正文。)考虑,例如,两个不同的章节树和从它们派生的 4 本书:
tree1: BookI[chap_s=tree1]: BookII[chap_s=tree1]:
1. Introduction I 1. Introduction 1. Introduction
2. Topic TA par1 par1
3. Topic TB 2. Topic TA 2. Topic TA
par2 par2
par3 3. Topic TB
3. Topic TB par4
par4 par5
tree2: BookIII[chap_s=tree2]: BookIV[chap_s=tree2]:
1. Topic TA 1. Topic TA 1. Topic TA
2. Topic TB par2 par3
2.1. Advanced AT1 2. Topic TB 2. Topic TB
2.2. Advanced AT2 par4 2.1 Advanced AT1
2.2.1 Special SCX 2.1 Advanced AT1 par6
par6 par8
2.2. Advanced AT2 2.2. Advanced AT2
2.2.1 Special SCX par9
par7 2.2.1 Special SCX
par7
对于ChapterTree,我可以尝试同时存储结构和标题,方法是使用包含标题["Introduction I", "Topic TA", "Topic TB"] 用于tree1 和["Topic TA", "Topic TB", ["Advanced AT1", "Advanced AT2", ["Special SCX"]]] 用于tree2 的字符串嵌套数组。然后对于 Book 内容,另一个 JSONField 包含一个数组,其中包含每个级别的段落实例的键数组,例如,四本书将是 [[1], [2, 3], [4]]、[[1], [2], [4,5]]、[[2], [4], [6], [], [7]] 和 [[3], [], [6,8], [9], [7]]。
这个想法很可能很糟糕?没有什么可以强制一致性;例如,如果通过在中间某处添加新的子章节来修改 ChapterTree 实例之一,则使用该树的所有书籍都将被破坏(而不是最终得到一个可以稍后填充的空子章节)。我真的希望有一个更优雅的解决方案。
【问题讨论】:
-
你研究过图形数据库吗? (这可能会有所帮助)。不使用我认为不能很好地与 Django 集成的另一种类型的数据库。使用 Django REST 中的序列化程序可能会成功,这样您就可以强制执行您正在寻找的逻辑。
标签: django django-models database-design