2013-03-03 1 views
1

Я пытаюсь добавить слой memcached pylibmc между sqlalchemy и моей почтой postgres. This post говорил о том, как это сделать. Но я также хочу backrefs (для перехода от одного к многим в отношениях), поэтому я изменил user_classes.py этого сообщения, чтобы проверить его.отсоединенный SQLalchemy сеанс не может лениться на загрузку backref объектов

Я создал UserStatus для наследования из базы данных.MemcachedORMObject и добавил backref в UserTable.mapper. Но я получаю экземпляр «DetachedInstanceError: Parent», не привязанный к Sessi, при попытке доступа к обратному файлу при работе с файлом «lessy load» атрибут «пользователь» не может действовать ». Я использую Flask-SQLAlchemy == 0.16, SQLAlchemy == 0.8.0b2 и pylibmc == 1.2.3.

class UserStatus(database.MemcachedORMObject):              
    def __init__(self, name):                  
     self.name = name                    

UserStatusTable = Table('user_status', METADATA, \             
    Column('user_status_id', Integer, primary_key=True),            
    Column('name', String)                   )                         
UserStatusTable.mapper = mapper(UserStatus, UserStatusTable)           
UserStatusTable.mapper.compile()                  


class User(database.MemcachedORMObject):                
    def __init__(self, name, email, password, user_status_id):          
     self.name = name                    
     self.email = email                   
     self.password = password                  
     self.user_status_id = user_status_id               

UserTable = Table('user', METADATA, \                
    Column('user_id', Integer, primary_key=True),             
    Column('name', String), 
    Column('email', String),                   
    Column('password', String),                  
    Column('user_status_id', Integer),                
    ForeignKeyConstraint(['user_status_id'], ['user_status.user_status_id'])       )                         
UserTable.mapper = mapper(User, UserTable, 
    properties = { 'user_status': relation(UserStatus, backref='user', lazy=False)})     
UserTable.mapper.compile() 

Ошибка при попытке получить доступ к backref:

In [14]: from user_classes import *         In [15]: ust = UserStatus.fetch_by_field(UserStatus.user_status_id, 1) Memcached Getting: user_classes.UserStatus:(1) In [16]: ust.user 
--------------------------------------------------------------------------- DetachedInstanceError      Traceback (most recent call last) <ipython-input-16-38fd625abed9> in <module>() 
----> 1 ust.user /home/david/sqlalchemy-memcached/env/lib/python2.7/site-packages/sqlalchemy/orm/attribut es.pyc in __get__(self, instance, owner) 
    249    return dict_[self.key] 
    250   else: 
--> 251    return self.impl.get(instance_state(instance), dict_) 
    252 
    253 /home/david/sqlalchemy-memcached/env/lib/python2.7/site-packages/sqlalchemy/orm/attribut es.pyc in get(self, state, dict_, passive) 
    543      value = callable_(passive) 
    544     elif self.callable_: 
--> 545      value = self.callable_(state, passive) 
    546     else: 
    547      value = ATTR_EMPTY /home/david/sqlalchemy-memcached/env/lib/python2.7/site-packages/sqlalchemy/orm/strategi es.pyc in _load_for_state(self, state, passive) 495     "Parent instance %s is not bound to a Session; " 
    496     "lazy load operation of attribute '%s' cannot proceed" %--> 497     (orm_util.state_str(state), self.key) 
    498   ) 
    499 DetachedInstanceError: Parent instance <UserStatus at 0x21e9dd0> is not bound to a Sessi on; lazy load operation of attribute 'user' cannot proceed 

ответ

1

Это ошибка в SQLAlchemy. Я сообщил об этом на трекер ошибок: http://www.sqlalchemy.org/trac/ticket/2743

Вы всегда можете пройти по направлению отношений по умолчанию. Поэтому обходным путем в вашем случае будет изменение направления отношений (так что вы можете получить доступ к пользователю из состояния пользователя, но не наоборот).

Общее обходное решение (если вам нужно пройти по обоим направлениям позже) заключается в том, чтобы исправить атрибут __dict__ в объекте, где определена обратная сторона. Для тестового теста на трекере ошибок это будет:

for p in parents: 
    for c in p.children: 
     getattr(c, '__dict__')['parent'] = p 
print parents[0].children[0].parent 
+0

Почему вы используете 'getattr (c, '__dict __')' вместо просто 'c .__ dict__'? –