SQLAlchemy, effacer de la base de données de contenu, mais ne laissez pas tomber le schéma
Je suis l'élaboration d'un Pylônes application qui est basée sur l'existant de la base de données, donc je suis en utilisant la réflexion. J'ai un fichier SQL avec le schéma que j'ai utilisé pour créer ma base de données de test. C'est pourquoi je ne peux pas tout simplement utiliser drop_all
et create_all
.
Je voudrais écrire des tests unitaires et j'ai affronté le problème de la compensation de la base de données de contenu après chaque test. Je veux juste effacer toutes les données, mais laissez les tables intacte. Est-ce possible?
L'application utilise Postgres et c'est ce qui doit être également utilisé pour les tests.
- Vous devez utiliser les transactions. docs.sqlalchemy.org/en/rel_0_7/orm/...
Vous devez vous connecter pour publier un commentaire.
J'ai demandé la même chose sur la SQLAlchemy groupe Google, et j'ai trouvé une recette qui semble bien fonctionner (tous mes tableaux sont vidées). Voir le fil de référence.
Mon code (extrait) ressemble à ceci:
Edit: j'ai modifié le code pour supprimer des tables dans l'ordre inverse; soi-disant, cela devrait s'assurer que les enfants sont supprimés avant que les parents.
for table in reversed(meta.Base.metadata.sorted_tables): meta.Session.execute(table.delete()); meta.Session.commit()
engine
viennent? Etcontextlib
? Est-ce que la bibliothèque standard? Cette réponse serait mieux si les importations étaient complets.meta
était, et donc le modifier a pas d'effet sur leur compréhension. Mais pour quelqu'un qui n'a jamais vuMetaData()
avant et il est juste de tâtonner dans une application de quelqu'un d'autre a créé, je crains que la réponse maintenant il fait regarder comme ils sont censés créer un nouvellesMetaData()
l'instance à utiliser avec ce code, qui bien sûr ne fonctionne pas.for table in engine.table_names(): con.execute("DROP table " + table)
Pour PostgreSQL à l'aide de
TRUNCATE
:Remarque:
RESTART IDENTITY;
s'assure que toutes les séquences sont réinitialisés. Cependant, c'est plus lent que leDELETE
recette par @aknuds1 de 50%.Une autre recette consiste à déposer tous les tableaux premier, puis les recréer. C'est plus lent par un autre 50%:
metadata.Base.metadata.drop_all(bind=engine)
donne l'erreurAttributeError: 'MetaData' object has no attribute 'Base'
L'utiliser truncate:
TRONQUER [ TABLE ] nom [, ...]
(http://www.postgresql.org/docs/8.4/static/sql-truncate.html)
Cela va supprimer tous les enregistrements dans la table, mais laissez le schéma de tact.
for table in meta.Base.metadata.tables.keys(): meta.Session.execute('truncate %s' % table); meta.Session.commit()
provoque un tel message d'erreur: "InternalError: (InternalError) transaction en cours est annulée, les commandes ignoré jusqu'à la fin de l'opération en bloc" tronquer les données.sous-mots-clés' {}"truncate %s cascade
mais c'est extrêmement lent. Trop lent à exécuter après chaque test unitaire...