J'ai une application django avec quatre modèles. Je réalise maintenant que l'un de ces modèles devrait être dans une application distincte. J'ai installé le sud pour les migrations, mais je ne pense pas que ce soit quelque chose qu'il puisse gérer automatiquement. Comment puis-je migrer l'un des modèles de l'ancienne application vers une nouvelle?
Aussi, gardez à l'esprit que je vais avoir besoin que ce soit un processus répétable, afin que je puisse migrer le système de production et autres.
django
migration
django-south
Apreche
la source
la source
Réponses:
Comment migrer en utilisant le sud.
Disons que nous avons deux applications: communes et spécifiques:
Maintenant, nous voulons déplacer le modèle common.models.cat vers une application spécifique (précisément vers specific.models.cat). Effectuez d'abord les modifications dans le code source, puis exécutez:
Nous devons maintenant modifier les deux fichiers de migration:
Maintenant, les deux migrations d'applications sont conscientes du changement et la vie est un peu moins pénible :-) L'établissement de cette relation entre les migrations est la clé du succès. Maintenant si vous faites:
effectuera à la fois la migration et
va migrer les choses vers le bas.
Notez que pour la mise à niveau du schéma, j'ai utilisé une application commune et pour la rétrogradation, j'ai utilisé une application spécifique. C'est parce que comment fonctionne la dépendance ici.
la source
orm['contenttypes.contenttype'].objects.filter
ligne dans la partie arrière de0003_create_cat
aussi? Je veux aussi partager une astuce. Si vous avez des index, ils devront également être modifiés. Dans mon cas, c'étaient des index uniques, donc mon attaquant ressemble à ça:db.delete_unique('common_cat', ['col1'])
db.rename_table('common_cat', 'specific_cat')
db.delete_unique('specific_cat', ['col1'])
orm['contenttypes.contenttype']
, vous devez également ajouter l'--freeze contenttypes
option à vosschemamigration
commandes.python manage.py schemamigration specific create_cat --auto --freeze common
pour accéder au modèle de chat depuis l'application commune.Misera sur la Potr Czachur de réponse , les situations qui impliquent ForeignKeys sont plus complexes et doivent être traitées de façon légèrement différente.
(L'exemple suivant s'appuie sur les applications
common
etspecific
référencées dans la réponse actuelle).changerait alors en
Fonctionnement
générerait les migrations suivantes (j'ignore intentionnellement les modifications de Django ContentType - voir la réponse précédemment référencée pour savoir comment gérer cela):
Comme vous pouvez le voir, le FK doit être modifié pour référencer la nouvelle table. Nous devons ajouter une dépendance afin que nous sachions l'ordre dans lequel les migrations seront appliquées (et donc que la table existera avant d'essayer d'y ajouter un FK) mais nous devons également nous assurer que le retour en arrière fonctionne aussi car le la dépendance s'applique dans le sens inverse .
Selon la documentation du sud ,
depends_on
garantira que0004_auto__add_cat
s'exécute avant0009_auto__del_cat
lors de la migration vers l'avant, mais dans l' ordre inverse lors de la migration vers l'arrière . Si nous restionsdb.rename_table('specific_cat', 'common_cat')
dans laspecific
restauration, lacommon
restauration échouerait lors de la tentative de migration de la clé étrangère car la table référencée n'existerait pas.Espérons que ce soit plus proche d'une situation «du monde réel» que les solutions existantes et que quelqu'un trouvera cela utile. À votre santé!
la source
Les modèles ne sont pas très étroitement liés aux applications, le déplacement est donc assez simple. Django utilise le nom de l'application dans le nom de la table de base de données, donc si vous souhaitez déplacer votre application, vous pouvez soit renommer la table de base de données via une
ALTER TABLE
instruction SQL , soit - encore plus simple - simplement utiliser ledb_table
paramètre dans laMeta
classe de votre modèle pour faire référence au ancien nom.Si vous avez utilisé des ContentTypes ou des relations génériques n'importe où dans votre code jusqu'à présent, vous souhaiterez probablement renommer le type
app_label
de contenu pointant sur le modèle en mouvement, afin que les relations existantes soient préservées.Bien sûr, si vous n'avez aucune donnée à conserver, le plus simple est de supprimer complètement les tables de la base de données et de les relancer
./manage.py syncdb
.la source
Voici une autre solution à l'excellente solution de Potr. Ajoutez ce qui suit à spécifique / 0003_create_cat
À moins que cette dépendance ne soit définie, Sud ne garantira pas que la
common_cat
table existe au moment de l' exécution de / 0003_create_cat spécifique, ce qui vous enverra unedjango.db.utils.OperationalError: no such table: common_cat
erreur.South exécute les migrations dans l' ordre lexicographique à moins que la dépendance ne soit explicitement définie. Puisque
common
vient avant quespecific
toutes lescommon
migrations de soient exécutées avant le changement de nom de table, il ne se reproduirait probablement pas dans l'exemple original montré par Potr. Mais si vous renommezcommon
enapp2
etspecific
en,app1
vous rencontrerez ce problème.la source
Le processus sur lequel je me suis actuellement arrêté depuis que je suis revenu ici plusieurs fois et que j'ai décidé de le formaliser.
Cela a été construit à l' origine sur la réponse de Potr Czachur et la réponse de Matt Briançon , en utilisant 0.8.4 du Sud
Étape 1. Découvrez les relations de clé étrangère enfant
Donc, dans ce cas étendu, nous avons découvert un autre modèle connexe comme:
Étape 2. Créer des migrations
Étape 3. Contrôle de la source: validez les modifications jusqu'à présent.
Cela en fait un processus plus répétable si vous rencontrez des conflits de fusion comme des coéquipiers écrivant des migrations sur les applications mises à jour.
Étape 4. Ajoutez des dépendances entre les migrations.
Cela
create_kittycat
dépend essentiellement de l'état actuel de tout, et tout dépend alors decreate_kittycat
.Étape 5. Le changement de nom de table que nous voulons apporter.
Étape 6. Seulement si vous avez besoin de backwards () pour travailler ET obtenir un KeyError à l'envers.
Étape 7. Testez-le - ce qui fonctionne pour moi n'est peut-être pas suffisant pour votre situation réelle :)
la source
Donc, utiliser la réponse originale de @Potr ci-dessus ne fonctionnait pas pour moi sur South 0.8.1 et Django 1.5.1. Je publie ci-dessous ce qui a fonctionné pour moi dans l'espoir que cela soit utile aux autres.
la source
Je vais donner une version plus explicite de l'une des choses suggérées par Daniel Roseman dans sa réponse ...
Si vous modifiez simplement l'
db_table
attribut Meta du modèle que vous avez déplacé pour qu'il pointe vers le nom de la table existante (au lieu du nouveau nom que Django lui donnerait si vous supprimiez et exécutiez asyncdb
), vous pouvez éviter des migrations Sud compliquées. par exemple:Original:
Après avoir déménagé:
Il vous suffit maintenant de faire une migration de données pour mettre à jour le
app_label
forMyModel
dans ledjango_content_type
tableau et vous devriez être prêt à partir ...Exécutez
./manage.py datamigration django update_content_type
puis modifiez le fichier que South crée pour vous:la source