8
votes

Déplacez un objet Python / Django d'un modèle parent à un enfant (sous-classe)

Je sous-classant un modèle existant. Je veux que beaucoup des membres de la classe mère soient maintenant, à la place, des membres de la classe enfant.

Par exemple, j'ai une hirondelle de modèle. Maintenant, je fais de l'Europeanswallowallow (avaler) et africainswallowallowallow (hirondelle). Je veux prendre des objets d'avaler mais pas tous les objets d'hirondelle ne les rendent pas européennes ou africainswallowallow, selon qu'ils sont migratoires.

Comment puis-je les déplacer?


0 commentaires

5 Réponses :


10
votes

C'est un peu de hack, mais cela fonctionne:

swallow = Swallow.objects.get(id=1)
swallow.__class__ = AfricanSwallow
# set any required AfricanSwallow fields here
swallow.save()


0 commentaires

0
votes

Je suggère d'utiliser Django-Model-Utils's InheritanCastmodel. C'est une implémentation que j'aime. Vous pouvez trouver beaucoup plus dans Djangosnippets et certains blogs, mais après avoir passé à tous ceux que j'ai choisi celui-ci. J'espère que cela aide.


0 commentaires

1
votes

dépend de quel type de héritage modèle que vous utiliserez. Voir http://docs.djangoproject.com/fr/dev / Thèmes / DB / Modèles / # Modèle-héritage pour les trois types classiques. Comme on dirait que vous voulez que vous souhaitiez des objets d'hirondelle qui excluent la classe de base abstraite.

Si vous souhaitez stocker différentes informations dans la DB pour avaler contre Africanswallow vs EuropeanSwallow, vous voudrez alors utiliser MTI. Le plus gros problème avec MTI, car le modèle officiel de Django recommande que le polymorphisme ne fonctionne pas correctement. C'est-à-dire que si vous recherchez un objet d'hirondelle de la DB qui est en fait un objet Africanswallow, vous n'obtiendrez pas une instance Of Africanswallallow. (Voir Cette question .) Quelque chose comme Django-modèle-utils inheritanCanager peut aider à surmonter cela. < / p>

Si vous avez des données réelles, vous devez conserver dans ce changement, utilisez Migrations Sud . Faites deux migrations - première qui change le schéma et une autre qui copie les données des objets appropriés en sous-classes.


0 commentaires

7
votes

Je sais que c'est beaucoup plus tard, mais j'avais besoin de faire quelque chose de similaire et de ne pas trouver beaucoup. J'ai trouvé la réponse enterrée dans un code source ici , mais a également écrit un exemple de méthode de classe qui suffirait.

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


1 commentaires

Hey - une réponse géniale. Cela fait longtemps que j'ai eu ce besoin. Naturellement, je suis un peu réticent à compter sur _méta dans une situation de production, mais c'est une telle vie. Merci!



0
votes

Une autre approche (dépassée): si cela ne vous dérange pas de garder l'identité du parent, vous ne pouvez créer de nouvelles instances d'enfants de l'attrai de parents. C'est ce que j'ai fait:

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()


0 commentaires