如何正确重命名 wagtail 页面模型

Posted

技术标签:

【中文标题】如何正确重命名 wagtail 页面模型【英文标题】:How to properly rename a wagtail page model 【发布时间】:2019-06-16 11:58:15 【问题描述】:

我在 wagtail 应用中有两个模型,PageTypeNewPageType,需要将 PageType 替换为 NewPageType

我想我可以从models.py 中删除PageType,然后运行迁移以将其删除,然后将NewPageType 重命名为PageType 并运行第二次迁移。

但是,我在执行此操作时遇到了错误:

[2019-01-22 23:20:26,344] [ERROR] Internal Server Error: /cms/
Traceback (most recent call last):
  File "/.../python3.6/site-packages/django/core/handlers/exception.py", line 41, in inner
    response = get_response(request)
  File "/.../python3.6/site-packages/django/core/handlers/base.py", line 187, in _get_response
    response = self.process_exception_by_middleware(e, request)
  [...snip...]
  File "/.../python3.6/site-packages/django/db/models/query.py", line 1121, in _fetch_all
    self._result_cache = list(self._iterable_class(self))
  File "/.../python3.6/site-packages/wagtail/core/query.py", line 397, in specific_iterator
    yield pages_by_type[content_type][pk]
KeyError: 278

Django 的内置迁移处理似乎没有自动更新某些内容。我不知道我在这里缺少哪些步骤,所以很想得到一些帮助。谢谢!

【问题讨论】:

【参考方案1】:

那是因为 Wagtail 页面使用 Multi-table inheritance 并且您删除的部分 PageType 页面仍然存在。

让我们看一下全新安装的 Wagtail(即 wagtail start mysite),它带有 home.HomePage 模型并默认创建一个 HomePage。我们可以看一下数据库,确认数据库中确实有一个条目:

sqlite> SELECT * FROM home_homepage;
page_ptr_id
3

但它相当空旷。没有标题,没有路径,只有page_ptr_id。这是因为HomePage 继承自非抽象的Page 模型。因此,该 Page 模型也有一个数据库表(这就是 Multi-table inheritance 与 Django 一起工作的方式)。我们来看看对应的表格(自愿省略一些列):

sqlite> SELECT id, path, title, slug, url_path, content_type_id FROM wagtailcore_page;
id|path    |title|slug|url_path|content_type_id
1 |0001    |Root |root|/       |1
3 |00010001|Home |home|/home/  |2

来了!

同样,在您的情况下,有 wagtailcore_pagemyapp_pagetypemyapp_newpagetype 表。通过删除PageType 模型,django 创建了一个迁移,然后删除了myapp_pagetype,但将条目留在了wagtailcore_page 表中。因此,现在,当您加载管理界面时,Wagtail 会尝试加载第 3 页但失败。

因此,在删除页面模型之前,您需要先删除所有页面。您可以通过在迁移中添加RunPython 步骤来实现此目的。

你仍然需要重命名你的第二个模型,虽然这对 Django 来说可能很困难,但如果你幸运的话,在你的 models.py 文件中重命名它并运行 makemigrations 可能足以让 Django 检测到它应该重命名模型。如果没有,或者如果您有需要重命名的关系,则可能涉及更多,请参阅1 和2。

【讨论】:

【参考方案2】:

要从中恢复并能够再次加载管理员,请执行以下操作:

删除引用:

import django
django.setup()
from wagtail.core.models import PageRevision
PageRevision.objects.filter(page_id= 278).delete()
exit()

然后删除页面。

django-admin dbshell
DELETE FROM wagtailcore_page WHERE id=278;

希望对您有所帮助。

【讨论】:

【参考方案3】:

我是 wagtail 的新手,但重命名模型和相关模板,然后运行没有问题

python manage.py makemigrations
python manage.py migrate

话虽如此,我并没有重复使用像 OP 这样的旧名称。我可能会建议遇到此问题的任何人为模型取一个新名称并使其具有描述性。

【讨论】:

以上是关于如何正确重命名 wagtail 页面模型的主要内容,如果未能解决你的问题,请参考以下文章

如何从默认 Django 模型重命名模型字段?

如何编写迁移以重命名 Rails 中的 ActiveRecord 模型及其表?

如何在 Fossil SCM 中重命名 wiki 页面?

Django - 如何使用 South 重命名模型字段?

当有外部引用时,如何重命名 Django 模型的文件夹?

如何在项目中重命名 Rails 控制器和模型