Move a python / django object from a parent model to a child (subclass)

后端 未结 5 1144
[愿得一人]
[愿得一人] 2021-01-03 01:44

I am subclassing an existing model. I want many of the members of the parent class to now, instead, be members of the child class.

For example, I have a model Swall

相关标签:
5条回答
  • 2021-01-03 01:56

    Depends on what kind of model inheritance you'll use. See http://docs.djangoproject.com/en/dev/topics/db/models/#model-inheritance for the three classic kinds. Since it sounds like you want Swallow objects that rules out Abstract Base Class.

    If you want to store different information in the db for Swallow vs AfricanSwallow vs EuropeanSwallow, then you'll want to use MTI. The biggest problem with MTI as the official django model recommends is that polymorphism doesn't work properly. That is, if you fetch a Swallow object from the DB which is actually an AfricanSwallow object, you won't get an instance o AfricanSwallow. (See this question.) Something like django-model-utils InheritanceManager can help overcome that.

    If you have actual data you need to preserve through this change, use South migrations. Make two migrations -- first one that changes the schema and another that copies the appropriate objects' data into subclasses.

    0 讨论(0)
  • 2021-01-03 02:00

    It's a bit of a hack, but this works:

    swallow = Swallow.objects.get(id=1)
    swallow.__class__ = AfricanSwallow
    # set any required AfricanSwallow fields here
    swallow.save()
    
    0 讨论(0)
  • 2021-01-03 02:08

    Another (outdated) approach: If you don't mind keeping parent's id you can just create brand new child instances from parent's attrs. This is what I did:

    ids = [s.pk for s in Swallow.objects.all()]
    # I get ids list to avoid memory leak with long lists
    for i in ids:
        p = Swallow.objects.get(pk=i)
        c = AfricanSwallow(att1=p.att1, att2=p.att2.....)
        p.delete()
        c.save()
    

    Once this runs, a new AfricanSwallow instance will be created replacing each initial Swallow instance Maybe this will help someone :)

    0 讨论(0)
  • 2021-01-03 02:10

    I suggest using django-model-utils's InheritanceCastModel. This is one implementation I like. You can find many more in djangosnippets and some blogs, but after going trough them all I chose this one. Hope it helps.

    0 讨论(0)
  • 2021-01-03 02:14

    I know this is much later, but I needed to do something similar and couldn't find much. I found the answer buried in some source code here, but also wrote an example class-method that would suffice.

    class AfricanSwallow(Swallow):
    
        @classmethod
        def save_child_from_parent(cls, swallow, new_attrs):
            """
            Inputs:
            - swallow: instance of Swallow we want to create into AfricanSwallow
            - new_attrs: dictionary of new attributes for AfricanSwallow
    
            Adapted from: 
            https://github.com/lsaffre/lino/blob/master/lino/utils/mti.py
            """
            parent_link_field = AfricanSwallow._meta.parents.get(swallow.__class__, None)
            new_attrs[parent_link_field.name] = swallow
            for field in swallow._meta.fields:
                new_attrs[field.name] = getattr(swallow, field.name)
            s = AfricanSwallow(**new_attrs)
            s.save()
            return s
    

    I couldn't figure out how to get my form validation to work with this method however; so it certainly could be improved more; probably means a database refactoring might be the best long-term solution...

    0 讨论(0)
提交回复
热议问题