2016-03-28 2 views
1

J'ai une application Django 1.9 qui exécute une section de code où des modifications sont apportées à la base de données en fonction des résultats des requêtes adressées à certaines API distantes. Par exemple, il peut s'agir de données sur les validations, les modifications de fichiers, les relecteurs, les demandes d'extraction, etc. que je veux enregistrer en tant qu'entités dans ma base de données.Utilisation de blocs atomiques avec gestion des erreurs dans Django

commit_data = commit_API_client.get_commit_info(argument1, argument2) 
new_commit = models.Commit.Create(**commit_data) 

#if the last API failed, this will fail 
#I will need to run this again to get these files, so I need 
#to get the commit all over again, too 
files = file_API_client.get_file_info(new_commit.id) 
new_files = models.Files.Create(**files) 

#do some more stuff here 

Il est très possible que l'une des quelques API que j'appelle renverra une erreur au lieu de données valides. J'ai essentiellement besoin de faire de cette section en une seule transaction atomique de sorte que s'il n'y a aucune erreur retournée par le HTTP requests, je valide tous les changements à la base de données. Sinon, je risque de perdre des données si 2 API retournent correctement, mais pas la 3ème.

J'ai vu que Django supportait commit hooks pour les transactions de base de données, mais je me demandais si cela serait applicable à cette situation et comment je m'y prendrais pour l'implémenter.

Répondre

4

Si vous voulez transformer cela en opération atomique, enveloppez-le simplement dans transaction.atomic(). Si l'un de vos codes déclenche une exception, le bloc entier sera annulé. Si vous effectuez uniquement des lectures à partir de l'API distante, cela devrait fonctionner correctement. Un modèle typique est:

def my_function(): 
    try: 
     with transaction.atomic(): 
      # Do your work here 
      pass 
    except Exception: 
     # Do some error handling 
     pass 

Django n'ont un on_commit hook, mais ce n'est pas vraiment applicable ici. Son but est d'exécuter du code après qu'une transaction s'est terminée avec succès. Par exemple, vous pouvez l'utiliser pour écrire des données de journal dans une API distante si la transaction a réussi.

+0

Est-ce que 'transaction.atomic()' quitte gracieusement dans le cas d'une exception? Tout cela est conçu autour de la gestion des erreurs, donc quand il y a une erreur, je dois 'excepter' l'exception et faire des enregistrements de l'erreur, le signaler à certains utilisateurs, etc. Ou dois-je appeler ma fonction d'une autre fonction cela fait un bloc 'try except' et fait la gestion des erreurs à partir de là? – skeletalbassman

+0

@skeletalbassman: Bien sûr, vous venez d'envelopper le bloc atomique dans une clause try-except. J'ai ajouté un exemple à la réponse. –

+0

Oui, ça fait l'affaire. J'ai adapté votre exemple et peux vérifier que cela fonctionne. – skeletalbassman