J'essaie de déterminer comment cartographier une simple propriété en lecture seule et que l'incendie de la propriété lorsque je sauvegarder dans la base de données.
Un exemple de contreveille devrait rendre cela plus clair. Premièrement, une table simple: p> Ce que je veux faire est de configurer une classe avec une propriété en lecture seule qui insère dans la colonne Calculée_value pour moi lorsque j'appelle la session .Commouver () ... p> class Foo(object):
def __init__(self, id, description):
self.id = id
self.description = description
self.items = []
self.some_other_items = []
@property
def item_sum(self):
self._item_sum = 0
for item in self.items:
self._item_sum += item.some_value
return self._item_sum
@property
def some_other_property(self):
self._some_other_property = 0
.... code to generate _some_other_property on the fly....
return self._some_other_property
mapper(Foo, metadata,
extension = UpdatePropertiesExtension(['item_sum', 'some_other_property']),
properties = {
'item_sum' : synonym('_item_sum', map_column=True),
'some_other_property' : synonym('_some_other_property', map_column = True)
})
3 Réponses :
Je ne suis pas sûr qu'il soit possible d'atteindre ce que vous voulez utiliser SQLALCHEMY.M.M.SYNONNONYNONY. Profondablement pas donné le fait que SQLalchemy tire la trace de laquelle les instances sont sales et doivent être mises à jour pendant la chasse.
Mais il y a d'une autre manière comment vous pouvez obtenir cette fonctionnalité - SessionExtensions (remarque la variable moteur_string au sommet qui doit être Rempli): P>
(env)zifot@localhost:~/stackoverflow$ cat stackoverflow.py engine_string = '' from sqlalchemy import Table, Column, String, Integer, MetaData, create_engine import sqlalchemy.orm as orm import datetime engine = create_engine(engine_string, echo = True) meta = MetaData(bind = engine) foo_table = Table('foo', meta, Column('id', String(3), primary_key=True), Column('description', String(64), nullable=False), Column('calculated_value', Integer, nullable=False), ) meta.drop_all() meta.create_all() class MyExt(orm.interfaces.SessionExtension): def before_commit(self, session): for obj in session: if isinstance(obj, Foo): obj.calculated_value = datetime.datetime.now().second + 10 Session = orm.sessionmaker(extension = MyExt())() Session.configure(bind = engine) class Foo(object): def __init__(self, id, description): self.id = id self.description = description orm.mapper(Foo, foo_table) (env)zifot@localhost:~/stackoverflow$ ipython Python 2.5.2 (r252:60911, Jan 4 2009, 17:40:26) Type "copyright", "credits" or "license" for more information. IPython 0.10 -- An enhanced Interactive Python. ? -> Introduction and overview of IPython's features. %quickref -> Quick reference. help -> Python's own help system. object? -> Details about 'object'. ?object also works, ?? prints more. In [1]: from stackoverflow import * 2010-06-11 13:19:30,925 INFO sqlalchemy.engine.base.Engine.0x...11cc select version() 2010-06-11 13:19:30,927 INFO sqlalchemy.engine.base.Engine.0x...11cc {} 2010-06-11 13:19:30,935 INFO sqlalchemy.engine.base.Engine.0x...11cc select current_schema() 2010-06-11 13:19:30,936 INFO sqlalchemy.engine.base.Engine.0x...11cc {} 2010-06-11 13:19:30,965 INFO sqlalchemy.engine.base.Engine.0x...11cc select relname from pg_class c join pg_namespace n on n.oid=c.relnamespace where n.nspname=current_schema() and lower(relname)=%(name)s 2010-06-11 13:19:30,966 INFO sqlalchemy.engine.base.Engine.0x...11cc {'name': u'foo'} 2010-06-11 13:19:30,979 INFO sqlalchemy.engine.base.Engine.0x...11cc DROP TABLE foo 2010-06-11 13:19:30,980 INFO sqlalchemy.engine.base.Engine.0x...11cc {} 2010-06-11 13:19:30,988 INFO sqlalchemy.engine.base.Engine.0x...11cc COMMIT 2010-06-11 13:19:30,997 INFO sqlalchemy.engine.base.Engine.0x...11cc select relname from pg_class c join pg_namespace n on n.oid=c.relnamespace where n.nspname=current_schema() and lower(relname)=%(name)s 2010-06-11 13:19:30,999 INFO sqlalchemy.engine.base.Engine.0x...11cc {'name': u'foo'} 2010-06-11 13:19:31,007 INFO sqlalchemy.engine.base.Engine.0x...11cc CREATE TABLE foo ( id VARCHAR(3) NOT NULL, description VARCHAR(64) NOT NULL, calculated_value INTEGER NOT NULL, PRIMARY KEY (id) ) 2010-06-11 13:19:31,009 INFO sqlalchemy.engine.base.Engine.0x...11cc {} 2010-06-11 13:19:31,025 INFO sqlalchemy.engine.base.Engine.0x...11cc COMMIT In [2]: f = Foo('idx', 'foo') In [3]: f.calculated_value In [4]: Session.add(f) In [5]: f.calculated_value In [6]: Session.commit() 2010-06-11 13:19:57,668 INFO sqlalchemy.engine.base.Engine.0x...11cc BEGIN 2010-06-11 13:19:57,674 INFO sqlalchemy.engine.base.Engine.0x...11cc INSERT INTO foo (id, description, calculated_value) VALUES (%(id)s, %(description)s, %(calculated_value)s) 2010-06-11 13:19:57,675 INFO sqlalchemy.engine.base.Engine.0x...11cc {'description': 'foo', 'calculated_value': 67, 'id': 'idx'} 2010-06-11 13:19:57,683 INFO sqlalchemy.engine.base.Engine.0x...11cc COMMIT In [7]: f.calculated_value 2010-06-11 13:20:00,755 INFO sqlalchemy.engine.base.Engine.0x...11cc BEGIN 2010-06-11 13:20:00,759 INFO sqlalchemy.engine.base.Engine.0x...11cc SELECT foo.id AS foo_id, foo.description AS foo_description, foo.calculated_value AS foo_calculated_value FROM foo WHERE foo.id = %(param_1)s 2010-06-11 13:20:00,761 INFO sqlalchemy.engine.base.Engine.0x...11cc {'param_1': 'idx'} Out[7]: 67 In [8]: f.calculated_value Out[8]: 67 In [9]: Session.commit() 2010-06-11 13:20:08,366 INFO sqlalchemy.engine.base.Engine.0x...11cc UPDATE foo SET calculated_value=%(calculated_value)s WHERE foo.id = %(foo_id)s 2010-06-11 13:20:08,367 INFO sqlalchemy.engine.base.Engine.0x...11cc {'foo_id': u'idx', 'calculated_value': 18} 2010-06-11 13:20:08,373 INFO sqlalchemy.engine.base.Engine.0x...11cc COMMIT In [10]: f.calculated_value 2010-06-11 13:20:10,475 INFO sqlalchemy.engine.base.Engine.0x...11cc BEGIN 2010-06-11 13:20:10,479 INFO sqlalchemy.engine.base.Engine.0x...11cc SELECT foo.id AS foo_id, foo.description AS foo_description, foo.calculated_value AS foo_calculated_value FROM foo WHERE foo.id = %(param_1)s 2010-06-11 13:20:10,481 INFO sqlalchemy.engine.base.Engine.0x...11cc {'param_1': 'idx'} Out[10]: 18
Intéressant. Même si j'ai résolu cela de manière légèrement différente, j'ai marqué cela comme la réponse parce que cela devrait fonctionner. Plus j'apprends sur Sqlalchemy, plus je l'aime!
Merci d'être modifié avec votre réponse, Jeff. J'ai eu le même problème et j'ai résolu l'utilisation de votre code, voici quelque chose de similaire pour ceux utilisant une base déclarative. Peut vous sauvegarder quelques minutes sur la manière de spécifier les arguments du mapper et les synonymes:
Merci! M'a sauvé un peu de temps en effet.
Les versions plus récentes de SQLalchemy prennent en charge quelque chose appelé Propriétés hybrides, qui vous permettent de définir des méthodes sous forme de setters pour enregistrer des valeurs calculées à la DB. P>
Je ne suis pas sûr de comprendre le problème que vous essayez de bien résoudre suffisamment pour donner un code d'exemple, mais en affectant ici pour quiconque qui trébuche à travers cela via Google. P>