我可以在 Wagtail 中使用递归的 ParentalKey 吗?
Can I use a recursive ParentalKey in Wagtail?
假设我在 Wagtail 应用程序中有以下模型:
# models.py
from django.db import models
from django.db.models.deletion import CASCADE
from wagtail.admin.edit_handlers import InlinePanel, FieldPanel
from modelcluster.models import ParentalKey, ClusterableModel
class Person(ClusterableModel):
name = models.CharField(max_length=300)
contact_for = ParentalKey(
'self', on_delete=CASCADE, null=True, related_name='contacts'
)
panels = [
FieldPanel('name'),
FieldPanel('contact_for'),
InlinePanel('contacts')
]
以及以下挂钩:
# wagtail_hooks.py
from wagtail.contrib.modeladmin.options import ModelAdmin, modeladmin_register
from home.models import Person
class PersonAdmin(ModelAdmin):
model = Person
menu_label = 'People'
menu_icon = 'list-ul'
menu_order = 200
add_to_settings_menu = False
exclude_from_explorer = False
list_display = ('name',)
search_fields = ('name',)
list_filter = ('contact_for',)
modeladmin_register(PersonAdmin)
当 运行 执行上述操作并导航到“管理”>“人员”>“添加人员”时,我将收到 RecursionError 异常(超出最大递归深度)。
我猜这是一个与 Wagtail 相关的问题,因为我可以按照 IPython:
中的预期使用 class
./manage.py shell -i ipython
In [1]: from home.models import Person
In [2]: mike = Person(name='Mike')
In [3]: mike.contacts = [Person(name='Sam'), Person(name='John')]
In [4]: mike.contacts
Out[4]: <modelcluster.fields.create_deferring_foreign_related_manager.<locals>.DeferringRelatedManager at 0x7f36e9548af0>
In [5]: mike.save()
In [6]: [person.name for person in Person.objects.all()]
Out[6]: ['Mike', 'Sam', 'John']
In [7]: Person.objects.all()[1].contact_for.name
Out[7]: 'Mike'
那么,有没有办法在 Wagtail 中使用递归 ParentalKey?我在做什么 wrong/missing?
编辑:我刚找到 。所以我想知道我是否应该为非页面模型尝试使用 ParentalKey(和 ParentalManyToManyField)。
编辑 2:对于任何感兴趣的人,我最终拆分了我的模型以避免递归键。 InlinePanels 与 ModelAdmin classes 一起工作,只是 Wagtail 似乎 不支持递归键。我还选择在合适的地方使用 Snippets 和 SnippetChooserPanel。
ParentalKey 意味着子模型在概念上被视为 'part of' 父模型并且不作为独立实体存在 - 例如,图片库是页面的一部分 - 用于诸如版本控制和审核工作流程。 (在Wagtail中,通过snippets或ModelAdmin处理的非页面模型不具备这些特性,但为了让它们与页面共享相同的InlinePanel机制,它们也使用了ParentalKey。)
在这种情况下,Person 不是另一个 Person 的一部分,需要独立于 'parent' 进行编辑,因此 ParentalKey 在这里不合适。相反,您应该使用 ForeignKey,它仅指示模型之间的某种关系。这确实意味着您不能使用 InlinePanel 来管理同一视图中的多个 Person 记录 - 您必须分别编辑它们,并使用 SnippetChooserPanel 之类的东西或简单的下拉菜单来设置它们之间的关系。
假设我在 Wagtail 应用程序中有以下模型:
# models.py
from django.db import models
from django.db.models.deletion import CASCADE
from wagtail.admin.edit_handlers import InlinePanel, FieldPanel
from modelcluster.models import ParentalKey, ClusterableModel
class Person(ClusterableModel):
name = models.CharField(max_length=300)
contact_for = ParentalKey(
'self', on_delete=CASCADE, null=True, related_name='contacts'
)
panels = [
FieldPanel('name'),
FieldPanel('contact_for'),
InlinePanel('contacts')
]
以及以下挂钩:
# wagtail_hooks.py
from wagtail.contrib.modeladmin.options import ModelAdmin, modeladmin_register
from home.models import Person
class PersonAdmin(ModelAdmin):
model = Person
menu_label = 'People'
menu_icon = 'list-ul'
menu_order = 200
add_to_settings_menu = False
exclude_from_explorer = False
list_display = ('name',)
search_fields = ('name',)
list_filter = ('contact_for',)
modeladmin_register(PersonAdmin)
当 运行 执行上述操作并导航到“管理”>“人员”>“添加人员”时,我将收到 RecursionError 异常(超出最大递归深度)。
我猜这是一个与 Wagtail 相关的问题,因为我可以按照 IPython:
中的预期使用 class./manage.py shell -i ipython
In [1]: from home.models import Person
In [2]: mike = Person(name='Mike')
In [3]: mike.contacts = [Person(name='Sam'), Person(name='John')]
In [4]: mike.contacts
Out[4]: <modelcluster.fields.create_deferring_foreign_related_manager.<locals>.DeferringRelatedManager at 0x7f36e9548af0>
In [5]: mike.save()
In [6]: [person.name for person in Person.objects.all()]
Out[6]: ['Mike', 'Sam', 'John']
In [7]: Person.objects.all()[1].contact_for.name
Out[7]: 'Mike'
那么,有没有办法在 Wagtail 中使用递归 ParentalKey?我在做什么 wrong/missing?
编辑:我刚找到
编辑 2:对于任何感兴趣的人,我最终拆分了我的模型以避免递归键。 InlinePanels 与 ModelAdmin classes 一起工作,只是 Wagtail 似乎 不支持递归键。我还选择在合适的地方使用 Snippets 和 SnippetChooserPanel。
ParentalKey 意味着子模型在概念上被视为 'part of' 父模型并且不作为独立实体存在 - 例如,图片库是页面的一部分 - 用于诸如版本控制和审核工作流程。 (在Wagtail中,通过snippets或ModelAdmin处理的非页面模型不具备这些特性,但为了让它们与页面共享相同的InlinePanel机制,它们也使用了ParentalKey。)
在这种情况下,Person 不是另一个 Person 的一部分,需要独立于 'parent' 进行编辑,因此 ParentalKey 在这里不合适。相反,您应该使用 ForeignKey,它仅指示模型之间的某种关系。这确实意味着您不能使用 InlinePanel 来管理同一视图中的多个 Person 记录 - 您必须分别编辑它们,并使用 SnippetChooserPanel 之类的东西或简单的下拉菜单来设置它们之间的关系。