Reputation: 21
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
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
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
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