Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

How to use methods like set_parent during manual RunPython in migrations? #42

Closed
jvacek opened this issue Oct 27, 2021 · 5 comments
Closed
Assignees
Labels
question Further information is requested

Comments

@jvacek
Copy link
Contributor

jvacek commented Oct 27, 2021

Python version
3.9.1

Django version
2.2.24

Package version
0.17.0

Current behaviour (bug description)
My model was previously using the MPTT library, and so I'd like to transfer to TreeNode. However I am not really able to do the migration due to the methods not being available when using the apps.get_model tactic, and I think directly working on the keys might not be a good idea seeing as set_parent has things going on.

def migrate_mptt_treenode(apps, schema_editor):
    MyModel = apps.get_model("myapp", "MyModel")
    for c in MyModel.objects.all():
        if c.parent is not None:
            c.set_parent(c.parent)
            c.save()

The info about the parent was stored in parent before, which is a TreeForeignKey Field from MPTT. I want to first migrate in the new fields from treenode, make the migration, and then remove the inheritance for the MPTTModel after the data is moved.

Expected behaviour
I know that apps.get_model doesn't make the methods available, so it's not that this should work. Some alternatives for this use-case would be helpful though.

@jvacek jvacek added the bug Something isn't working label Oct 27, 2021
@fabiocaccamo
Copy link
Owner

@jvacek the set_parent method is just a shortcut with some additional checks, I think that the code you shown should work correctly.

Alternatively, if your relation is already safe you can just set the tn_parent_id value (to the id of the parent object) and then call the save method.

If performances are important during the migration you can disable signals and update the tree manually -> MyModel.update_tree() at the end of the migration, check how this is done here.

@fabiocaccamo fabiocaccamo added help wanted Extra attention is needed question Further information is requested and removed bug Something isn't working labels Oct 27, 2021
@fabiocaccamo
Copy link
Owner

@jvacek any update?

@jvacek
Copy link
Contributor Author

jvacek commented Nov 2, 2021

We've ended up using the block below, which is quite sub-optimal given that we need to import the model to get access to the functions. We needed to run update_tree in order to trigger the right refreshes.

def migrate_mptt_treenode(apps, schema_editor):
    MyModel = apps.get_model("app", "MyModel")
    models = MyModel.objects.all()
    if models:
        for m in models:
            if m.parent is not None:
                m.tn_parent_id = m.parent.id
                m.save()

        from project.app.models import MyModel as MyModelButImported

        if hasattr(MyModelButImported, "update_tree") and callable(MyModelButImported.update_tree()):
            MyModelButImported.update_tree()

It would be nice if there was a cleaner way to access the functions during migrations.

@fabiocaccamo fabiocaccamo removed the help wanted Extra attention is needed label Nov 6, 2021
@fabiocaccamo
Copy link
Owner

@jvacek update_tree is a class method, even moving it to an external function you would have to pass the model class of the tree you want to update as argument, so I don't think that this problem would be solved.

Have you any suggestion?

@fabiocaccamo
Copy link
Owner

@jvacek any feedback?

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
question Further information is requested
Projects
None yet
Development

No branches or pull requests

2 participants