2016-10-10 3 views
4

J'utilise SQLAlchmey comme ORM pour un projet python. J'ai créé quelques modèles/schémas et ça fonctionne bien. Maintenant, j'ai besoin d'interroger une base de données mysql existante, pas d'insertion/mise à jour juste l'instruction select.sqlalchemy requête de base de données existante

Comment créer un wrapper autour des tables de cette base de données existante? J'ai brièvement passé par les documents sqlalchemy et SO, mais je n'ai rien trouvé de pertinent. Tous suggèrent la méthode d'exécution, où j'ai besoin d'écrire les requêtes sql brutes, tandis que je veux utiliser la méthode de requête SQLAlchmey de la même manière que j'utilise avec les modèles SA.

Par exemple, si le db existant a Nom de la table utilisateur alors je veux interroger à l'aide de la DBSession (seule la opération de sélection, probablement avec JOIN)

+0

Vous utiliseriez [réflexion] (http://docs.sqlalchemy.org/en/latest/core/reflection.html), et [automap] (http://docs.sqlalchemy.org/en/latest/orm/extensions/automap.html) si vous voulez travailler avec des classes mappées. –

Répondre

3

Vous semblez avoir une impression que SQLAlchemy ne peut fonctionner avec un structure de base de données créée par SQLAlchemy (probablement en utilisant MetaData.create_all()) - ce n'est pas correct. SQLAlchemy peut parfaitement fonctionner avec une base de données préexistante, il vous suffit de définir vos modèles pour correspondre aux tables de base de données. Une façon de le faire est d'utiliser la réflexion, comme Ilja Everilä suggère:

class MyClass(Base): 
    __table__ = Table('mytable', Base.metadata, 
        autoload=True, autoload_with=some_engine) 

(qui, à mon avis, serait tout à fait bien pour les scripts ponctuels mais peut conduire à des bugs incroyablement frustrant dans un « vrai » application si la structure de la base de données peut changer au fil du temps)

Une autre façon est de simplement définir vos modèles comme d'habitude en prenant soin de définir vos modèles pour correspondre aux tables de la base de données, ce qui n'est pas si difficile. L'avantage de cette approche est que vous pouvez mapper uniquement un sous-ensemble de tables de base de données à vos modèles et même uniquement un sous-ensemble de colonnes de table aux champs de votre modèle. Supposons que vous avez 10 tables dans la base de données, mais seulement intéressé par users la table où vous avez seulement besoin id, name et email champs:

class User(Base): 
    id = sa.Column(sa.Integer, primary_key=True) 
    name = sa.Column(sa.String) 
    email = sa.Column(sa.String) 

(notez comment on n'a pas besoin de définir certains détails qui ne sont nécessaires pour émet un DDL correct, tel que la longueur des champs String ou le fait que le champ email a un index)

SQLAlchemy n'émettra pas de requêtes INSERT/UPDATE sauf si vous créez ou modifiez des modèles dans votre code. Si vous souhaitez vous assurer que vos requêtes sont en lecture seule, vous pouvez créer un utilisateur spécial dans la base de données et accorder à cet utilisateur des privilèges SELECT uniquement. Alternativement/en plus, vous pouvez également expérimenter avec l'annulation de la transaction dans votre code d'application.

+0

Merci, Bien que j'ai utilisé automap avec la réflexion, mais votre suggestion semble aussi bien. Pour les utilisateurs SO, si vous avez le temps, vous pouvez également ajouter un exemple d'Automap. Cela rendra cette réponse complète – DevC

+0

@DevC: merci, j'ai ajouté un exemple – Sergey

0

Vous pouvez accéder à une table existante en utilisant le code suivant:

from sqlalchemy.orm import Session 

Base = automap_base() 
Base.prepare(engine, reflect=True) 
Users = Base.classes.users 
session = Session(engine) 
res = session.query(Users).first()