user10947439
user10947439

Reputation: 21

How to properly rename a wagtail page model

I have two models in a wagtail app, PageType and NewPageType, and need to replace PageType with NewPageType.

I thought I could remove PageType from my models.py and then run a migration to remove it, and then rename NewPageType to PageType and run a second migration.

However, I'm running into errors when I do this:

[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

It seems like something didn't get updated automatically by Django's built-in migration handling. I couldn't tell what steps I'm missing here so would love to get some help. Thanks!

Upvotes: 2

Views: 1677

Answers (3)

dev-jeff
dev-jeff

Reputation: 311

I'm new to wagtail, but I had no issues renaming the model and the correlating template, then running

python manage.py makemigrations
python manage.py migrate

That being said, I was not reusing an old name like OP. I might recommend anyone having this issue to come up with a new name for the model and make it a descriptive one.

Upvotes: 0

kundan
kundan

Reputation: 1288

To recover from it and be able to load admin again, do the following:

Delete the reference:

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

Then delete the page.

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

Hope that helps.

Upvotes: 1

Loïc Teixeira
Loïc Teixeira

Reputation: 1434

That's because Wagtail pages uses Multi-table inheritance and part of your deleted PageType pages are still around.

Let's take a look at a fresh install of Wagtail (i.e. wagtail start mysite) which comes with a home.HomePage model and creates one HomePage by default. We can have a look at the database and confirm that there is indeed an entry in the database:

sqlite> SELECT * FROM home_homepage;
page_ptr_id
3

However it's rather empty. There's no title, no path, nothing but a page_ptr_id. This is because the HomePage inherit from the Page model which isn't abstract. Therefore, there is a database table for that Page model as well (this is how Multi-table inheritance works with Django). Let's have a look at the corresponding table (voluntarily ommitting some columns) :

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

Here it is!

Similarly, in your case, there is the wagtailcore_page, the myapp_pagetype and myapp_newpagetype tables. By deleting the PageType model, django created a migration which then deleted the myapp_pagetype but left the entry in the wagtailcore_page table. Therefore now, when you load the admin interface, Wagtail tries to load the page #3 but fail to do so.

For that reason, before deleting a Page model, you need to delete all the pages first. You can achieve this by adding a RunPython step to your migration.

You would still be left with renaming your second model though which can be difficult with Django, although if you're lucky, renaming it in your models.py file and runing makemigrations might be enough for Django to detect that it should rename the model. If not, or if you have relationships which need to be renamed to, it might be more involed, see 1 and 2.

Upvotes: 4

Related Questions