Gestion transactionnelle de la base de données
Django vous apporte plusieurs moyens pour contrôler la gestion transactionnelle de la base de données, si vous utilisez une base de données qui supporte les transactions.
Comportement transactionnel par défaut de Django
Le comportement par défaut de Django est d'envoyer les modifications automatiquement lorsque toute fonction de construction ou d'altération de modèle est appelée. Par exemple, si vous appelez model.save() ou model.delete(), la modification sera immédiatement envoyée.
Cela ressemble à la configuration auto-commit de la plupart des bases de données. Dès que vous avez effectué une action qui nécessite une écriture en base de données, Django génère les commandes INSERT/UPDATE/DELETE puis effectue un COMMIT. Il n'y a aucun ROLLBACK implicite.
Lier des transactions aux requêtes HTTP
Pour gérer la liaison des transactions aux requêtes HTTP il est recommandé de lier ces dernières aux phases de requête et réponse via le TransactionMiddleware de Django.
Ceci marche ainsi: quand une requête débute, Django initie une transaction. Si la réponse est produite sans aucun problème, Django envoie toute transaction en attente. Si la fonction de vue génère une exception, Django revient en arrière sur toute transaction en attente.
Pour activer cette fonctionnalité, ajoutez simplement le middleware TransactionMiddleware à votre paramètre de configuration MIDDLEWARE_CLASSES:
MIDDLEWARE_CLASSES = (
'django.contrib.sessions.middleware.SessionMiddleware',
'django.middleware.common.CommonMiddleware',
'django.middleware.cache.CacheMiddleware',
'django.middleware.transaction.TransactionMiddleware',
)
L'ordre est très important. Le middleware de transaction s'applique non seulement aux fonctions de vue, mais aussi à tous les middlewares du module qui suivent. Ainsi, si vous placez le middleware de session après le middleware de transaction, la création de session fera partie de la transaction.
L'exception est le CacheMiddleware, qui ne sera jamais affecté. Le middleware de cache utilise son propre curseur de base de données (mappé sur sa propre connexion interne à la base de données).
Contrôler la gestion transactionnelle dans les vues
Pour la plupart des gens, les transactions basés sur les requêtes implicites fonctionnent parfaitement. Cependant, si vous avez besoin d'une granularité plus poussée sur la gestion transactionnelle, vous pouvez utiliser les décorateurs Python afin de modifier la gestion des transactions pour une fonction de vue donnée.
Note
Bien que les exemples ci-dessous utilisent des fonctions de vue comme exemple, ces décorateurs peuvent être tout aussi bien appliqués à d'autres fonctions qui ne sont pas des vues.
django.db.transaction.autocommit
Utilisez le décorateur autocommit pour affecter une fonction de vue au comportement d'envoi par défaut de Django, qui dépend du paramètre de configuration global.
Exemple:
from django.db import transaction
@transaction.autocommit
def ma_vue(request):
....
A l'intérieur de ma_vue(), les transactions seront envoyées dès que vous appellerez model.save(), model.delete(), ou tout autre méthode écrivant en base de données.
django.db.transaction.commit_on_success
Utilisez le décorateur commit_on_success pour définir une transaction unique contenant tout le travail effectué dans la fonction:
from django.db import transaction
@transaction.commit_on_success
def ma_vue(request):
....
Si la fonction se termine avec succès, Django enverra alors tout le travail contenu dans la fonction jusqu'à ce point. Si la fonction lève une exception, Django reviendra en arrière sur la transaction.
django.db.transaction.commit_manually
Utilisez le décorateur commit_manually si vous avez besoin d'un contrôle complet au niveau des transactions. Cela indiquera à Django que vous gérerez vous même les transactions.
Si votre fonction de vue modifie des données et que les fonctions commit() ou``rollback()`` ne sont pas appelées, Django lèvera une exception TransactionManagementError.
La gestion manuelle des transactions ressemble à ceci:
from django.db import transaction
@transaction.commit_manually
def ma_vue(request):
...
# Vous pouvez appeler commit/rollback où et quand vous le voulez
transaction.commit()
...
# Mais vous devez vous rappeler de le faire vous même !
try:
...
except:
transaction.rollback()
else:
transaction.commit()
Note importante pour les utilisateurs de la version précédente de Django:
Les méthodes de base de données connection.commit() et connection.rollback() (appelées db.commit() et db.rollback() dans les version 0.91 et précédentes) n'existent plus. Elles ont été remplacées par transaction.commit() et transaction.rollback().
Comment globalement désactiver la gestion transactionnelle
Les personnes le désirant peuvent complètement désactiver la gestion transactionnelle en assignant le paramètre de configuration DISABLE_TRANSACTION_MANAGEMENT à True dans le ficher de configuration Django.
Si vous faîtes cela, Django ne fournira aucun système automatique de gestion transactionnelle quel qu'il soit. Le Middleware n'enverra aucune transaction implicite, et vous devrez gérez le retour en arrière par vous même. Ceci implique aussi que vous envoyiez les changements effectués par le middleware quelque part dans votre application.
Ainsi, c'est l'utilisation idéale lorsque vous souhaitez exécuter votre propre gestion transactionnelle de middleware ou quelque chose de vraiment spécial. Dans la plupart des situations, vous ferez mieux d'utiliser le comportement par défaut, ou le middleware de transaction, et uniquement modifier les fonctions choisies comme désiré.
Transactions MySQL
Si vous utilisez MySQL, vos tables peuvent supportées ou non les transactions; cela dépend de votre version de MySQL et du type de table que vous utilisez. (Par "type de table", nous entendons quelque chose comme "InnoDB" ou "MyISAM".) Les particularités des transactions MySQL dépassent le champ de cet article, mais le site de MySQL possède des informations sur les transactions MySQL.
Si votre configuration MySQL ne supporte pas les transactions, Django fonctionnera en mode auto-commit: Les commandes seront exécutées et envoyées dès qu'appelées. Si votre configuration MySQL supporte les transactions, Django gérera les transactions comme détaillé dans ce document.