Skip to content

Basic migration guide for those coming from FeinCMS #59

Open

Description

@ds-cbo

Hi there, I'm working on migrating a code base we have from FeinCMS to feincms3 to get some new features and fixes in, but I am sadly quite stuck* and cannot seem to find any type of migration guide anywhere. I am aware that feincms3 is a new project with drastically different layouts and ideas etc than FeinCMS, but I would really appreciate a vague direction of how to transfer content from one to the other.

The migration doesn't have to be exactly 1:1 as that's probably not possible, but if FeinCMS would have some general "export to JSON" guide and feincms3 could have some general "import from JSON" guide (similar to Django's fixtures), even if the JSON schema themselves would change, it would already feel more manageable. At this point it almost feels easier to do everything by hand, but considering our amount of content that would get annoying really fast

Thanks!

* both code-wise and content-wise, but I think code-wise should be more manageable with the available documentation

Activity

  1. matthiask commented on Jul 17, 2026

    @matthiask
    Member

    Hi @ds-cbo

    I'm glad to hear both projects are useful and I'm a bit sad about the pain the migration causes.

    I have been working a long time on a project where we did a gradual migration from FeinCMS to feincms3. You'll probably be glad to hear that the FeinCMS 1 content types (I'm going to call them plugins also from now on in this response) and the feincms3 plugins are basically 1:1 the same as long as the model and/or form fields themselves are equivalent.

    What we did was (adapted to mention pages and not chapters):

    • We let FeinCMS 1 manage the plugin models
    • We added feincms3 plugins with managed = False in class Meta so that Django didn't actually think that those were new or different models, we also set db_table to the value which FeinCMS would autogenerate. For example, db_table = page_page_richtextcontent.
    • We migrated the model admin to use ContentEditor instead of ItemEditor. Because it is a large textbook digitization platform we had a chapter proxy per book series, and we therefore could migrate book series by book series. If you "only" use one page hierarchy, you would do this migration in one step).
    • We gradually moved the code over from using FeinCMS rendering to feincms3 rendering piece by piece. We had to migrate the HTML generation for the frontend, the indexers for the full text search implementation and other stuff which had to render the content.

    After everything was migrated I was able to drop managed = False from all feincms3 plugins and remove FeinCMS altogether, even from the project requirements. At this point I was able to delete all migration files for the apps and recreate them from scratch, and apply them using ./manage.py migrate --fake-initial. Please note that this is somewhat dangerous, changing migration files is strongly discouraged but if you're absolutely sure that the "before" and "after" schemas are the same it's safe, and a good way to remove references to code which you are removing completely. I do not remember all the details (this work was mainly done in 2024 and 2025) but I think I compared the schemas by diffing the pg_dump --schema-only output or something like that.

    A specific snag you will also hit is that FeinCMS uses django-mptt, and the default feincms3 page uses django-tree-queries. Thanks to Mariusz we have a guide which explains how to migrate the page tree:
    https://django-tree-queries.readthedocs.io/en/latest/#migrating-from-django-mptt

    We are still running with db_table set to the values expected by FeinCMS. I never got around to dropping this and letting the migration framework rename the tables. That said, having hardcoded db_table values isn't harmful at all, and everything works just as it should. When we add new plugins, we do not add db_table anymore and let Django do its thing.

    So, you shouldn't even have to go the JSON dumping/loading route, you should be able to just use the same tables and access them from both FeinCMS and feincms3 code.

    I hope this is useful!

  2. matthiask commented on Jul 18, 2026

    @matthiask
    Member

    One addendum to my earlier reply, after actually re-checking what I did in the project this was based on: for the very last step (dropping managed = False once every plugin has been converted), I originally suggested deleting all migrations, recreating them from scratch and applying with ./manage.py migrate --fake-initial.

    Looking back at the actual history, what I used there instead was Django's migrations.SeparateDatabaseAndState operation. It lets you change the migration state ("this table is now modelled by this Django model") without touching the database, model by model, as each one becomes ready -- instead of resetting an entire app's migration history in one go. Much smaller blast radius, and it fits the gradual, piece-by-piece nature of the rest of this migration better than a single big-bang --fake-initial step at the end.

    I've also written this whole approach up in a bit more detail: https://406.ch/writing/migrating-from-feincms-to-feincms3/

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Metadata

Metadata

Assignees

No one assigned

    Type

    No type

    Projects

    No projects

      Milestone

      No milestone

      Relationships

      None yet

      Development

      No branches or pull requests

      Issue actions