Wagtail: Loading and saving pages from a Django dumpdata file changes their content types

Created on 2 Jun 2015  路  2Comments  路  Source: wagtail/wagtail

When dumping the content of an existing database with the following command:

$> django-admin.py dumpdata --natural-foreign --indent=4 -e contenttypes -e auth.Permission -e sessions > /tmp/my_wagtail_data.json

I get a dump of all data in my database as a JSON fixture that can be loaded onto other database instances (e.g. other developer machines).

However, when I save a page in the Wagtail UI, the "type" of the page changes. For example, if I have a "Basic" page and I go to save it, it gets changed into a "Blog Post" page. I would expect that the content types would not change.

Looking into the datamodels of the data dump, this bug occurs as a result of wagtailcore.pagerevision records that are in the file. When playing around with the dumpdata command, I learned that the IDs of the contenttypes models are not guaranteed to be the same across database instances because Django automatically creates these records for the user. To get around this, one has to NOT include the contentypes in the data dump (-e contenttypes) and use the --natural-foreign argument to have models use the natural key strings (instead of ID numbers) for attributes that refer to foreign keys.

The reason wagtailcore.pagerevision screws this up is because it does not use the natural keys for foreign attributes in the JSON it stores for its records. This results in the JSON containing the following content:

{
    // ...other attributes....
    "content_type": 26
    // ...other attributes....
}

This results in the situation of when Page models are saved, the ID they refer to as the content type may refer to something that is not expected at all.

To recreate this situation:

  1. $> django-admin.py dumpdata --natural-foreign --indent=4 -e wagtailredirects.redirect -e contenttypes -e auth.Permission -e sessions > /tmp/my_wagtail_data.json
  2. $> django-admin.py reset_db --noinput
  3. $> django-admin.py migrate --no-initial-data
  4. $> django-admin.py loaddata /tmp/my_wagtail_data.json
  5. Start your app server, open a browser and go to edit a page
  6. Save/publish an existing page
  7. On the index list of pages, the type of the page has changed
Bug

Most helpful comment

# Workaround

To work around this issue, I exclude the wagtailcore.pagerevision in my data dump:

$> django-admin.py dumpdata --natural-foreign --indent=4 -e contenttypes -e auth.Permission -e sessions -e wagtailcore.pagerevision

This means that the data dump will NOT contain any historical page revisions.

All 2 comments

# Workaround

To work around this issue, I exclude the wagtailcore.pagerevision in my data dump:

$> django-admin.py dumpdata --natural-foreign --indent=4 -e contenttypes -e auth.Permission -e sessions -e wagtailcore.pagerevision

This means that the data dump will NOT contain any historical page revisions.

How I triggered the problem:

  • edit models.py and change the order of the class definitions (ie: move one class to end of file, change nothing else)
  • ./manage.py makemigrations && ./manage.py migrate
  • Edit an existing page of the type that was moved (or any type of page in between the moved block of code), when you save, the content type will be set wrong but all fields still exist in the database.
  • Seems like the new content_type is set based on the last revision's content_type and not the actual content_type found in the django table(s).

Solution:

  • Use dumpdata, including the revisions table
  • For all of the pages of the moved class type, change the content_type ID to match what it's actually migrated to
  • Use re-create the database and loaddata from the editing fixture

Problem summary:

  • When you change the order of classes in models.py, the content_type IDs change during migration however, the revision table's entries are not updated to reflect the migration changes.

Proposed solution:

  • Fix makemigrations to include the revision table edits necessary to maintain consistency
Was this page helpful?
0 / 5 - 0 ratings