Ne peut pas exécuter des requêtes jusqu'à la fin de la atomique en bloc dans ma migration des données sur django 1.7
J'ai une assez longue migration de données que je suis en train de faire pour corriger le plus tôt mauvais migration, où certaines lignes ont été créées de manière incorrecte. Je suis en train d'affecter des valeurs à une nouvelle colonne basée sur les anciens, cependant, cela conduit parfois à des erreurs d'intégrité. Lorsque cela arrive, j'ai envie de jeter celui qui est la cause de l'erreur d'intégrité
Voici un extrait de code:
def load_data(apps, schema_editor):
MyClass = apps.get_model('my_app', 'MyClass')
new_col_mapping = {old_val1: new_val1, ....}
for inst in MyClass.objects.filter(old_col=c):
try:
inst.new_col = new_col_mapping[c]
inst.save()
except IntegrityError:
inst.delete()
Puis dans le fonctionnement de mon Migration
classe je ne
operations = [
migrations.RunPython(load_data)
]
J'obtiens l'erreur suivante lors de l'exécution de la migration
django.db.transaction.TransactionManagementError: An error occurred in the current transaction. You can't execute queries until the end of the 'atomic' block
J'ai le sentiment que cela
with transaction.atomic():
quelque part c'est ma solution mais je ne suis pas sûr de savoir exactement où le droit de place est. Plus important encore, je voudrais comprendre POURQUOI cela est nécessaire
OriginalL'auteur sedavidw | 2015-08-25
Vous devez vous connecter pour publier un commentaire.
Ceci est similaire à la exemple dans les docs.
Tout d'abord, ajouter l'importation, si vous ne l'avez pas déjà.
Enrouler ensuite le code qui pourrait soulever une erreur d'intégrité dans un bloc atomique.
La raison de l'erreur est expliqué dans le bloc avertissement 'Éviter d'attraper les exceptions à l'intérieur atomique!" dans les docs. Une fois Django rencontre une erreur de base de données, il sera de remettre le bloc atomique. Tentez plus de requêtes de base de données sera la cause d'une
TransactionManagementError
, vous voyez. En enveloppant le code dans un bloc atomique, seulement que le code sera annulée, et vous pouvez exécuter des requêtes à l'extérieur du bloc.OriginalL'auteur Alasdair
Chaque migration est enroulé autour d'une transaction, de sorte que quand quelque chose tombe en panne au cours de la migration, toutes les opérations seront annulées. À cause de cela, chaque opération au cours de laquelle quelque chose a échoué, ne peuvent pas prendre de nouvelles requêtes (elles seront annulées de toute façon).
Habillage de certaines opérations avec
with transaction.atomic():
n'est pas la bonne solution, car vous ne pourrez pas annuler cette opération quand quelque chose va échouer. Au lieu de cela, éviter les erreurs d'intégrité en faisant un peu plus de vérifications avant l'enregistrement des données.transaction.atomic()
est une "mauvaise" solution si c'est ce que je vais faire de toute façon. Ces lignes ont été effectués de manière incorrecte et sont en fait mal, et je veux me débarrasser d'euxOriginalL'auteur GwynBleidD
Il semble que la même exception peut avoir une variété de causes. Dans mon cas, cela a été causé par une défaillance de modèle nom du champ: j'ai utilisé une lettre grecque delta
dans mon domaine nom.
Il semblait bien fonctionner, l'app a bien fonctionné (peut-être je ne l'ai pas essayer plus complexes de cas d'utilisation). Les tests, cependant, a soulevé
TransactionManagementError
.J'ai résolu le problème en supprimant
à partir du nom du champ et de tous les fichiers de migration.
OriginalL'auteur Eerik Sven Puudist