2017-09-05 5 views
0

Je souhaite créer une relation 1: n entre deux tables dynamiquement. Mon modèle de base de données est mappé via SQLAlchemy mais en raison de certaines fonctionnalités spéciales de mon application, je ne peux pas utiliser la méthode déclarative par défaut.SQLAlchemy: comment créer une relation par programme

E.g.

class Foo(Base): 
    id = Column(Integer, autoincrement=True, primary_key=True) 
    flag = Column(Boolean) 

class Bar(Base): 
    id = Column(Integer, autoincrement=True, primary_key=True) 
    foo_id = Column(Integer, ForeignKey('foo.id')) 
    # declarative version: 
    # foo = relationship(Foo) 

Je veux ajouter relation nommé « foo » à la classe mappée « Bar » après Bar a été défini et SQLAlchemy a fait son travail de définition d'un mappeur etc.

Mise à jour 2017-09 -05: Pourquoi est-ce nécessaire pour moi? (J'ai pensé que je pourrais omettre cela parce que je pense que cela détourne le problème de résoudre le problème, mais puisqu'il y avait des commentaires ...)

Tout d'abord, je n'ai pas une seule base de données mais des centaines/milliers. Les données des anciennes bases de données ne doivent en aucun cas être modifiées, mais je souhaite qu'un code source unique accède aux anciennes données (même si la structure des données et les règles de calcul changent de manière significative).

Actuellement, nous utilisons plusieurs définitions de modèles. Les définitions ultérieures étendent/modifient les précédentes. Souvent, nous manipulons les modèles SQLAlchemy dynamiquement. Nous essayons de ne pas avoir de code dans les classes mappées car nous pensons qu'il sera beaucoup plus difficile d'assurer l'exactitude de ce code après avoir changé une table plusieurs fois (le code doit fonctionner à chaque étape intermédiaire).

Dans de nombreux cas, nous étendons les tables (classes mappées) par programmation dans le modèle X après sa définition initiale dans le modèle X-1. L'ajout de colonnes à une classe SQLAlchemy ORM existante est gérable. Maintenant, nous ajoutons une nouvelle colonne de référence à une table existante et une relationship() fournit une API Python plus agréable.

+0

Quelle est la raison derrière cela? Voulez-vous utiliser comme une liste externe de modèles à utiliser lors de la création de plusieurs relations? – krassowski

+0

Ajoutez simplement un attribut de relation à la classe, bien que @krassowski ait raison: pourquoi avez-vous besoin de ça? –

+0

@ ilja-everilä: Pouvez-vous élaborer? J'ai besoin que la définition de la relation soit complètement découplée de la déclaration réelle. Fondamentalement, je veux savoir comment manipuler les internes de SQLAlchemy mais je ne pouvais pas trouver les bonnes sections dans les (très bons) docs et j'espérais que quelqu'un pourrait me sauver quelques heures de lecture du code source SQLAlchemy ... :-) –

Répondre

0

Eh bien, ma question ci-dessus est encore un bel exemple de super pouvoirs de sqlalchemy (et ma compréhension limitée):

Bar.__mapper__.add_property('foo', relationship('Foo')) 

probable que je ne pouvais pas obtenir ce travail d'abord parce que certains de mon code environnant mélangé en ajoutant des relations et des colonnes. En outre il y a une différence importante dans les colonnes déclarant:

Column('foo', Integer) 

Pour les colonnes du premier paramètre peut être le nom de la colonne, mais vous ne pouvez pas l'utiliser pour les relations. relationship('foo', 'Foo') déclenche des exceptions lors de la transmission à .add_property().