2009-06-10 9 views
9

Je suis assez novice dans l'utilisation de bases de données relationnelles. Je préfère donc utiliser un bon ORM pour simplifier les choses. J'ai passé du temps à évaluer différents ORM Python et je pense que SQLAlchemy est ce dont j'ai besoin. Cependant, je suis arrivé à une impasse mentale.Création dynamique de tables et mappage ORM dans SqlAlchemy

Je dois créer une nouvelle table pour accompagner chaque instance d'un joueur que je crée dans la table des joueurs de mon application. Je pense que je sais comment créer la table en changeant le nom de la table à travers les métadonnées puis en appelant la fonction de création, mais je n'ai aucune idée sur la façon de le mapper à une nouvelle classe dynamique. Est-ce que quelqu'un peut me donner quelques conseils pour m'aider à surmonter mon gel du cerveau? Est-ce seulement possible?

Note: Je suis ouvert à d'autres ORM en Python si ce que je demande est plus facile de implement.Just me montrer comment :-)

+2

Création de tables dynamiques est un mauvaise idée. Ajouter une clé à une table pour distinguer les instances des joueurs est une bonne idée. Qu'essayez-vous d'accomplir avec cette entreprise «table dynamique»? –

+0

Fondamentalement, chaque joueur obtient sa propre table de scores pour suivre leurs scores au fil du temps. Un joueur pourrait être ajouté à n'importe quel moment, il serait donc très difficile de le suivre dans une table de scores géante avec tous les joueurs ... du moins pour moi. –

+3

Bien sûr, le fait de poser la question me fait réfléchir d'une toute nouvelle manière. Je pourrais probablement créer une énorme table de scores qui inclue l'identifiant du joueur dans une colonne ainsi que son score. Je pourrais alors faire une recherche sur l'identifiant du joueur pour tirer leurs scores. Merci à tous. –

Répondre

20

Nous sommes absolument gâtés par sqlalchemy.
Ce qui suit est pris directement à partir du tutorial,
et il est vraiment facile à installer et se mettre au travail.

Et parce qu'il est fait si souvent,
Mike Bayer a fait encore plus facile
avec le all-in-one "declarative" method.

Configuration de votre environnement (j'utilise SQLite en mémoire db pour tester):

>>> from sqlalchemy import create_engine 
>>> engine = create_engine('sqlite:///:memory:', echo=True) 
>>> from sqlalchemy import Table, Column, Integer, String, MetaData 
>>> metadata = MetaData() 

Définir votre table: Si vous avez l'enregistrement se

>>> players_table = Table('players', metadata, 
... Column('id', Integer, primary_key=True), 
... Column('name', String), 
... Column('score', Integer) 
...) 
>>> metadata.create_all(engine) # create the table 

, vous aurez voir le SQL que SqlAlchemy crée pour vous.

Définir votre classe:

>>> class Player(object): 
...  def __init__(self, name, score): 
...   self.name = name 
...   self.score = score 
... 
...  def __repr__(self): 
...  return "<Player('%s','%s')>" % (self.name, self.score) 

affecter la classe à votre table:

>>> from sqlalchemy.orm import mapper 
>>> mapper(Player, players_table) 
<Mapper at 0x...; Player> 

Créer un joueur:

>>> a_player = Player('monty', 0) 
>>> a_player.name 
'monty' 
>>> a_player.score 
0 

C'est, vous avez maintenant une table de joueur .
En outre, le googlegroup SqlAlchemy est génial.
Mike Bayer est très rapide pour répondre aux questions.

+2

Merci pour l'info. Pas tout à fait ce que je cherchais. J'essayais quelque chose au-delà de ça, une autre table par joueur. –

3

Peut-être regarder la soupe sql, qui est couche sur sqlalchemy http://www.sqlalchemy.org/trac/wiki/SqlSoup

ou élixir (encore une enveloppe sur sqlalchemy) http://elixir.ematia.de/trac/wiki

vous pouvez également créer table en utilisant sql simple et à la carte dynamique utiliser ces libs si elles ne sont pas déjà créer la fonction de table.

ou de créer une classe dynamique et de la mapper, par ex. extrait de mon propre code

tableClass = type(str(table.fullname), (BaseTable.BaseTable,), {}) 
mapper(tableClass, table) 

où BaseTable peut être une classe de python que vous voulez que toutes vos classes de table à hériter de, par exemple une telle classe de base peut avoir une certaine utilité ou des méthodes communes, par ex. méthodes CRUD de base

class BaseTable(object): pass 

passent autrement vous ne devez pas les bases de type(...)

+0

Où puis-je importer BaseTable? Je ne peux pas le trouver dans sqlalchemy. –

+0

@Peter Hoffmann, réponse éditée. –

+0

Elixir n'a pas été mis à jour depuis 2009 et semble avoir été abandonné. Il n'a aucun support pour python 2.7+. – Mike

1

vous pouvez utiliser la méthode déclarative pour créer des tables dynamiquement dans la base

from sqlalchemy.ext.declarative import declarative_base 
from sqlalchemy import Table, Column, Integer, String, MetaData, ForeignKey 


Base = declarative_base() 

class Language(Base): 
    __tablename__ = 'languages' 

    id = Column(Integer, primary_key=True) 
    name = Column(String(20)) 
    extension = Column(String(20)) 

    def __init__(self, name, extension): 
     self.name = name 
     self.extension = extension 
0

peut-être que je ne comprenais pas tout à fait ce que vous voulez, mais cette recette créer colonne identique dans différents __tablename__

class TBase(object): 
    """Base class is a 'mixin'. 
    Guidelines for declarative mixins is at: 

    http://www.sqlalchemy.org/docs/orm/extensions/declarative.html#mixin-classes 

    """ 
    id = Column(Integer, primary_key=True) 
    data = Column(String(50)) 

    def __repr__(self): 
     return "%s(data=%r)" % (
      self.__class__.__name__, self.data 
     ) 

class T1Foo(TBase, Base): 
    __tablename__ = 't1' 

class T2Foo(TBase, Base): 
    __tablename__ = 't2' 

engine = create_engine('sqlite:///foo.db', echo=True) 

Base.metadata.create_all(engine) 

sess = sessionmaker(engine)() 

sess.add_all([T1Foo(data='t1'), T1Foo(data='t2'), T2Foo(data='t3'), 
     T1Foo(data='t4')]) 

print sess.query(T1Foo).all() 
print sess.query(T2Foo).all() 
sess.commit() 

info in example sqlalchemy

Questions connexes