0
votes

I followed the instructions from the Wagtail site for adding Wagtail to an existing Django project. At the end of the instructions, it said:

Note that there’s one small difference when not using the Wagtail project template: Wagtail creates an initial homepage of the basic type Page, which does not include any content fields beyond the title. You’ll probably want to replace this with your own HomePage class - when you do so, ensure that you set up a site record (under Settings / Sites in the Wagtail admin) to point to the new homepage.

I would like to change the 'basic type Page' to my model class BlogIndex. I know I can add the BlogIndex as a subpage of the default one and then point to it as described in the instructions. Instead, I would like to change the existing page. It bugs me having an unused page at the root. It would be a cleaner approach just to use it.

After adding my new class and migrating it, the django_content_type table looked like this:

1,admin,logentry
2,auth,permission
3,auth,group
4,auth,user
5,contenttypes,contenttype
6,sessions,session
7,wagtailcore,page
8,wagtailadmin,admin
9,wagtaildocs,document
10,wagtailimages,image
11,wagtailforms,formsubmission
12,wagtailredirects,redirect
13,wagtailembeds,embed
14,wagtailusers,userprofile
15,wagtailimages,rendition
16,wagtailimages,uploadedimage
17,wagtailsearch,query
18,wagtailsearch,querydailyhits
19,wagtailcore,grouppagepermission
20,wagtailcore,pagerevision
21,wagtailcore,pageviewrestriction
22,wagtailcore,site
23,wagtailcore,collection
24,wagtailcore,groupcollectionpermission
25,wagtailcore,collectionviewrestriction
26,taggit,tag
27,taggit,taggeditem
28,blog,blogindex

There is another table: wagtailcore_pages that contains three rows:

1,0001,1,1,Root,root,true,false,/,"",false,"",,,false,7
3,000100010001,3,0,Blog Index,blog-index,true,false,/blog/blog-index/,"",false,"",,,false,28
2,00010001,2,1,Welcome to your new Wagtail site!,home,true,false,/blog/,"",false,"",,,false,7

The last column is the content_type_id, which maps to the table above. I tried changing the value from 7 to 28. When I went to access the page in Wagtail admin, I got the error:

DoesNotExist at /cms/pages/2/
BlogIndex matching query does not exist.
Request Method: GET
Request URL:    http://localhost:8006/cms/pages/2/
Django Version: 3.0.7
Exception Type: DoesNotExist
Exception Value:    
BlogIndex matching query does not exist.
Exception Location: /Users/curt/htdocs/zetcho/venv/lib/python3.8/site-packages/django/db/models/query.py in get, line 415
Python Executable:  /Users/curt/htdocs/zetcho/venv/bin/python
Python Version: 3.8.2

This happened before and after I added the the BlogIndex page that you see in the wagtailcore_pages. Both were after I ran the migration to add it to the model. When I change it back to 7, everything is back to normal. My guess is that it's looking for the model in the wrong place.

I then created a standalone Wagtail app to see how it was different. The start of django_content_type table looked like this:

1,wagtailcore,page
2,home,homepage
3,wagtailadmin,admin

The app_label 'home' is the name of the app that the wagtail process created. The home app has a model file with a HomePage class in it.

The wagtailcore_pages for the stand alone app contains two rows:

1,0001,1,1,Root,root,1,0,/,"",0,"",,,0,1
3,00010001,2,0,Home,home,1,0,/home/,"",0,"",,,0,2

It's interesting that the id for the second row is 3 (the first column is id). Given the field is auto increment, a row with the id 2 must have been added and then deleted. The only thing I did after the migration to do runserver to insure it worked.

Clearly, I'm missing another step or two to get it to work assuming that's even possible. Any idea what they might be?

There's a two or three year old ticket on the Wagtail site regarding the setting of the default page, but on solution.

Update

I attempted what I understood to be @gasman's solution. The wagtail_core_page now looks like this:

1,0001,1,1,Root,root,true,false,/,"",false,"",,,false,7
5,000100010001,3,0,Blog Index,blog-index,true,false,/blog/blog-index/,"",false,"",,,false,28
2,00010001,2,1,Welcome to your new Wagtail site!,home,true,false,/blog/,"",false,"",,,false,28

The only change here is setting the page type for the second row to 28. I also changed the blog_blogindex table to this:

2,<p>Introduction</p>

The first column had been five. I've added and deleted a few times, thus the five. I stopped and restarted the application and got the following error when I added /cms to the url:

KeyError at /cms/
5
Request Method: GET
Request URL:    http://localhost:8006/cms/
Django Version: 3.0.7
Exception Type: KeyError
Exception Value:    
5
Exception Location: /Users/curt/htdocs/zetcho/venv/lib/python3.8/site-packages/wagtail/core/query.py in specific_iterator, line 403
Python Executable:  /Users/curt/htdocs/zetcho/venv/bin/python
Python Version: 3.8.2

My guess is because I still have the third row in the wagtail_core table above. I had that row in order to get a row to appear in the blog_blogindex table. I next tried to delete the row with the five in it and got a postgre/SQL error:

[23503] ERROR: update or delete on table "wagtailcore_page" violates foreign key constraint "wagtailcore_pagerevi_page_id_d421cc1d_fk_wagtailco" on table "wagtailcore_pagerevision" Detail: Key (id)=(5) is still referenced from table "wagtailcore_pagerevision".

After realizing I misread @gasman's clearly worded response, I added a second row to blog_blogindex:

5,<p>Introduction</p>
2,<p>unused page</p>

There only needs to be the one entry: the second one. I changed the seven to 28 in the wogtailcore_page for the row created as part of the setup. Wagtail ran without errors and the default page is using the BlogIndex class.

I had an additional problem: the site row was deleted. I'm pretty sure that was a result of me deleting the page to which it was pointing. I had changed the default home page in settings. I just added the row back and I was good. I should have changed the site row back first.

The Fix

  1. Add Wagtail to your project following the Wagtail instructions
  2. Add a model class for the home/base page you wish to use. I set mine up in a separate app.
  3. Run makemigrations and migrate.
  4. You should back up your database at this point in case things go horribly wrong in the next steps. You will be manually changing table data.
  5. Access the database and add the row to the new created class table as described by @gasman.
  6. Change the content_type_id column in wagtailcore_page of the second row to the id of the newly create class. There should only be two rows with the first one being the root. You can find the id in the django_content_type table.
  7. Commit your changes and run your app.
1

1 Answers

1
votes

The missing step is to create an entry in the blog_blogindex table with page_ptr_id=2, to accompany the wagtailcore_page record. Wagtail uses multi-table inheritance for Page objects, so the data for a BlogIndex instance is split between wagtailcore_page (which contains the fields common to all Page models) and blog_blogindex (which contains the fields defined on BlogIndex specifically).

However, I'm not aware of any way to create a blog_blogindex entry through the Django ORM as a standalone operation - if you try it, it will attempt to create a new wagtailcore_page entry at the same time. The 'home' app in the standalone project works around this (in the 0002_create_homepage migration) by deleting the old Page instance and creating a HomePage to replace it (creating entries in both wagtailcore_page and home_homepage) - this results in the missing ID 2. If you really wanted to avoid this deletion/recreation step in your own app, you'd presumably have to create the blog_blogindex entry with a raw SQL INSERT query.