2013-04-22 41 views
8

Tôi có đoạn mã sau:SQLAlchemy __init__ không chạy

session = scoped_session(sessionmaker(autocommit=False, autoflush=True, bind=engine)) 

Base = declarative_base() 
Base.query = session.query_property() 

class CommonBase(object): 
    created_at = Column(DateTime, default=datetime.datetime.now) 
    updated_at = Column(DateTime, default=datetime.datetime.now, onupdate=datetime.datetime.now) 

class Look(Base, CommonBase): 
    __tablename__ = "looks" 
    id = Column(Integer, primary_key=True) 

    def __init__(self): 
    print "__init__ is run" 
    Base.__init__(self) 
    self.feedback = None 

    def set_feedback(self, feedback): 
    """Status can either be 1 for liked, 0 no response, or -1 disliked. 
    """ 
    assert feedback in [1, 0, -1] 
    self.feedback = feedback 

    def get_feedback(self): 
    return self.feedback 

Và Tôi nhận được lỗi sau:

Traceback (most recent call last): 
    File "/Volumes/Data2/Dropbox/projects/Giordano/venv/lib/python2.7/site-packages/flask/app.py", line 1701, in __call__ 
    return self.wsgi_app(environ, start_response) 
    File "/Volumes/Data2/Dropbox/projects/Giordano/venv/lib/python2.7/site-packages/flask/app.py", line 1689, in wsgi_app 
    response = self.make_response(self.handle_exception(e)) 
    File "/Volumes/Data2/Dropbox/projects/Giordano/venv/lib/python2.7/site-packages/flask/app.py", line 1687, in wsgi_app 
    response = self.full_dispatch_request() 
    File "/Volumes/Data2/Dropbox/projects/Giordano/venv/lib/python2.7/site-packages/flask/app.py", line 1360, in full_dispatch_request 
    rv = self.handle_user_exception(e) 
    File "/Volumes/Data2/Dropbox/projects/Giordano/venv/lib/python2.7/site-packages/flask/app.py", line 1358, in full_dispatch_request 
    rv = self.dispatch_request() 
    File "/Volumes/Data2/Dropbox/projects/Giordano/venv/lib/python2.7/site-packages/flask/app.py", line 1344, in dispatch_request 
    return self.view_functions[rule.endpoint](**req.view_args) 
    File "/Volumes/Data2/Dropbox/projects/Giordano/src/giordano/web/backend.py", line 94, in wrapped 
    ret = f(*args, **kwargs) 
    File "/Volumes/Data2/Dropbox/projects/Giordano/src/giordano/web/backend.py", line 81, in decorated 
    return f(*args, **kwargs) 
    File "/Volumes/Data2/Dropbox/projects/Giordano/src/giordano/web/backend.py", line 187, in next 
    json_ret = ge.encode(results)  # automatically pulls the tags 
    File "/System/Library/Frameworks/Python.framework/Versions/2.7/lib/python2.7/json/encoder.py", line 201, in encode 
    chunks = self.iterencode(o, _one_shot=True) 
    File "/System/Library/Frameworks/Python.framework/Versions/2.7/lib/python2.7/json/encoder.py", line 264, in iterencode 
    return _iterencode(o, 0) 
    File "/Volumes/Data2/Dropbox/projects/Giordano/src/giordano/__init__.py", line 54, in default 
    jsonable = self.convert_to_jsonable(obj) 
    File "/Volumes/Data2/Dropbox/projects/Giordano/src/giordano/__init__.py", line 40, in convert_to_jsonable 
    image_url=obj.image_url, feedback=obj.get_feedback()) 
    File "/Volumes/Data2/Dropbox/projects/Giordano/src/giordano/models.py", line 100, in get_feedback 
    return self.feedback 
AttributeError: 'Look' object has no attribute 'feedback' 

Dường như với tôi rằng phương pháp __init__ của tôi không chạy như tôi có thể' t xem bất kỳ báo cáo in nào trong nhật ký của tôi.

Ai đó có thể giải thích lý do tại sao __init__ của tôi không chạy và tôi có thể làm gì cho điều này?

Trả lời

25

Kiểm tra các SQLAlchemy documentation on reconstruction:

The SQLAlchemy ORM does not call __init__ when recreating objects from database rows. The ORM’s process is somewhat akin to the Python standard library’s pickle module, invoking the low level __new__ method and then quietly restoring attributes directly on the instance rather than calling __init__ .

If you need to do some setup on database-loaded instances before they’re ready to use, you can use the @reconstructor decorator to tag a method as the ORM counterpart to __init__ . SQLAlchemy will call this method with no arguments every time it loads or reconstructs one of your instances. This is useful for recreating transient properties that are normally assigned in your __init__ :

from sqlalchemy import orm 

class MyMappedClass(object): 
    def __init__(self, data): 
     self.data = data 
     # we need stuff on all instances, but not in the database. 
     self.stuff = [] 

    @orm.reconstructor 
    def init_on_load(self): 
     self.stuff = [] 

When obj = MyMappedClass() is executed, Python calls the __init__ method as normal and the data argument is required. When instances are loaded during a Query operation as in query(MyMappedClass).one(), init_on_load is called.

+1

Cảm ơn vì sự hiểu biết. Tôi đã xem qua các tài liệu cho "instantiation object" và không bao giờ nghĩ về thuật ngữ "reconstruction"! – disappearedng

+0

Thực ra, tôi không chắc liệu họ có sử dụng từ đó trong tài liệu hay không, nhưng có vẻ như bản chất của ORM có nghĩa là có nhiều chi tiết nhỏ như thế này không rõ ràng ngay lập tức. Không có tập hợp thuật ngữ chuẩn nào giúp dễ dàng biết được cụm từ tìm kiếm nào cần sử dụng. –

+0

Tôi không chắc chắn nếu tôi thích hành vi này hay không ... Nó gây ra một số hiệu ứng thực sự kỳ lạ trong mã của tôi. Nhưng ít nhất tôi biết nó bây giờ làm thế nào các thực thể được xây dựng. –

Các vấn đề liên quan