11
votes

Comment remplacer un nom de colonne dans SQLalchemy en utilisant la réflexion et la syntaxe descriptive

Bonjour J'essaie de porter une application héritée à Python avec Sqlalchemy.

La base de données existante de l'application compte environ 300 tables et dans chaque table, une colonne nommée def tel que: p>

mine       : _table_ ....
TokenMcGuy : __tablename__ = 'accnt'
             __table_args__ = {'autoload': True}


2 commentaires

Parce que vous définissez la classe pour utiliser une table que vous avez déjà faite, par opposition à la perte de votre classe le générer automatiquement de vos attributs. Vous ne pouvez pas créer plus de colonnes après avoir défini une table


@JDI Votre commentaire fait beaucoup plus de sens après l'explication de TokenmacGuy. Mais je pense que vous dites tous les deux la même chose pendant que TMG explique un peu plus :)


3 Réponses :


3
votes

Vous pouvez définir votre table de cette façon: xxx


2 commentaires

Je sais, mais j'aimerais utiliser la réflexion. Sans réflexion, ce serait une énorme quantité de codage. Parce que la base de données que j'essaie d'accéder est une base de données existante avec de nombreuses tables ...


TokenmacGuyy fait à peu près la même chose, mais avec de meilleurs exemples et clartés :-)



19
votes

Vous pouvez avoir votre gâteau et le manger aussi. Définissez les colonnes que vous souhaitez renommer; Sqlalchemy déduira automatiquement toutes les colonnes que vous ne mentionnez pas.

>>> from sqlalchemy import *
>>> from sqlalchemy.ext.declarative import declarative_base
>>> 
>>> engine = create_engine("sqlite:///:memory:")
>>> 
>>> engine.execute("""
... create table accnt (
...     id integer primary key,
...     code varchar(20),
...     def varchar(50)
... )
... """)
<sqlalchemy.engine.base.ResultProxy object at 0x2122750>
>>> 
>>> Base = declarative_base()
>>> 
>>> Base.metadata.bind = engine
>>> 
>>> class Accnt(Base):
...     __tablename__ = 'accnt'
...     __table_args__ = {'autoload': True}
...     def_ = Column('def', String)
... 
>>> Accnt.def_
<sqlalchemy.orm.attributes.InstrumentedAttribute object at 0x2122e90>
>>> Accnt.code
<sqlalchemy.orm.attributes.InstrumentedAttribute object at 0x2127090>
>>> 


4 commentaires

Merci ! J'ai essayé de cette façon avec le code ci-dessous moteur = create_engine ('firebird: // sysdba: masterkey@127.0.0.1/d: \\ prj \\ db2 \\ \\ \ \ \\ db2 \\ \ \ win1254', echo = false) métadata = métadonnées () dbsession = sessionmaker (Bind = moteur) base = déclaratif_base () Classe ACCNT (base): __ table__ = table ('Accnt', métadonnées, autoload = true, autoload_with = moteur) _def = colonne ("DEF" (50) ) mais j'ai toujours "sqlalchemy.exc.argumentError: impossible d'ajouter une colonne supplémentaire" def 'lors de la spécification Table ' "" Quelle est la différence entre ces deux aduches?


@CTENGIZ - Je pense que c'est parce que la façon dont vous le faites, la table a déjà été générée. Si vous souhaitez spécifier différents attributs nommés pour vos colonnes, vous devez le faire en ligne.


Veuillez poster votre code dans votre question initiale; Il est presque impossible de donner un sens à cela lorsque vous le mettez dans un commentaire.


Avant votre réponse, j'ai trouvé une solution sale: accnt.defi = getattr (Accnt, 'def') qui n'est pas élégant et pythonique et conduira probablement d'autres problèmes ..



1
votes

Ceci peut être trop de force brute, mais une autre approche consiste à utiliser la bibliothèque sqlacodegen pour générer automatiquement tous les modèles de votre dB, puis modifier les personnes manuellement ou tweak sqlacodegen < / Code> Pour construire les modèles à l'aide de vos conventions. Il est en faveur de la cartographie des mots réservés à d'autres symboles.

voir https://pypi.python.org/pypi/sqlacodegen . Bel outil.


0 commentaires