2015-11-30 12 views
5

Tôi có chế độ xem Flask sử dụng SQLAlchemy để truy vấn và hiển thị một số bài đăng trên blog. Tôi đang chạy ứng dụng của mình bằng mod_wsgi. Chế độ xem này hoạt động lần đầu tiên tôi truy cập trang nhưng trả lại lỗi 500 lần sau. Traceback hiển thị lỗi ProgrammingError: SQLite objects created in a thread can only be used in that same thread. Tại sao tôi nhận được lỗi này và cách khắc phục?Sử dụng phiên SQLAlchemy từ Flask tăng "Các đối tượng SQLite được tạo trong một chuỗi chỉ có thể được sử dụng trong cùng một chuỗi"

views.py

engine = create_engine('sqlite:////var/www/homepage/blog.db') 
Base.metadata.bind = engine 
DBSession = sessionmaker(bind = engine) 
session = DBSession() 

@app.route('/blog') 
@app.route('/blog.html') 
def blog(): 
    entrys = session.query(Entry).order_by(desc(Entry.timestamp)).all() 
    return render_template('blog.html', blog_entrys = entrys) 

models.py:

class Entry(Base): 
    __tablename__ = 'entry' 

    id = Column(Integer, primary_key = True) 

    title = Column(String(100), nullable = False) 
    body = Column(String, nullable = False) 
    timestamp = Column(DateTime, nullable = False) 
    featured = Column(Boolean, nullable = False) 

    comments = relationship('Comment') 

    def is_featured(self): 
     return self.featured 


class Comment(Base): 
    __tablename__ = 'comment' 

    id = Column(Integer, primary_key = True) 
    entry_id = Column(Integer, ForeignKey('entry.id')) 

    text = Column(String(500), nullable = False) 
    name = Column(String(80)) 


engine = create_engine('sqlite:////var/www/homepage/blog.db') 
Base.metadata.create_all(engine) 
Exception on /blog.html [GET] 
Traceback (most recent call last): 
    File "/usr/lib/python2.6/dist-packages/flask/app.py", line 861, in wsgi_app 
    rv = self.dispatch_request() 
    File "/usr/lib/python2.6/dist-packages/flask/app.py", line 696, in dispatch_request 
    return self.view_functions[rule.endpoint](**req.view_args) 
    File "/var/www/homepage/webserver.py", line 38, in blog 
    entrys = session.query(Entry).order_by(desc(Entry.timestamp)).all() 
    File "/usr/lib/python2.6/dist-packages/sqlalchemy/orm/query.py", line 1453, in all 
    return list(self) 
    File "/usr/lib/python2.6/dist-packages/sqlalchemy/orm/query.py", line 1565, in __iter__ 
    return self._execute_and_instances(context) 
    File "/usr/lib/python2.6/dist-packages/sqlalchemy/orm/query.py", line 1570, in _execute_and_instances 
    mapper=self._mapper_zero_or_none()) 
    File "/usr/lib/python2.6/dist-packages/sqlalchemy/orm/session.py", line 735, in execute 
    clause, params or {}) 
    File "/usr/lib/python2.6/dist-packages/sqlalchemy/engine/base.py", line 1157, in execute 
    params) 
    File "/usr/lib/python2.6/dist-packages/sqlalchemy/engine/base.py", line 1235, in _execute_clauseelement 
    parameters=params 
    File "/usr/lib/python2.6/dist-packages/sqlalchemy/engine/base.py", line 1348, in __create_execution_context 
    None, None) 
    File "/usr/lib/python2.6/dist-packages/sqlalchemy/engine/base.py", line 1343, in __create_execution_context 
    connection=self, **kwargs) 
    File "/usr/lib/python2.6/dist-packages/sqlalchemy/engine/default.py", line 381, in __init__ 
    self.cursor = self.create_cursor() 
    File "/usr/lib/python2.6/dist-packages/sqlalchemy/engine/default.py", line 523, in create_cursor 
    return self._connection.connection.cursor() 
    File "/usr/lib/python2.6/dist-packages/sqlalchemy/pool.py", line 383, in cursor 
    c = self.connection.cursor(*args, **kwargs) 
ProgrammingError: (ProgrammingError) SQLite objects created in a thread can only be used in that same thread.The object was created in thread id 140244498364160 and this is thread id 140244523542272 None [{}] 

Trả lời

6

SQLAlchemy (và trong trường hợp này SQLite cũng) không hoạt động nếu bạn chia sẻ một phiên trên chủ đề. Bạn có thể không sử dụng chủ đề một cách rõ ràng, nhưng mod_wsgi là và bạn đã xác định đối tượng session toàn cầu. Sử dụng scoped_session để xử lý việc tạo phiên duy nhất cho từng chuỗi.

session = scoped_session(sessionmaker(bind=engine)) 

@app.teardown_request 
def remove_session(ex=None): 
    session.remove() 

@app.route('/') 
def example(): 
    item = session.query(MyModel).filter(...).all() 
    ... 

Tốt hơn, hãy sử dụng Flask-SQLAlchemy để xử lý việc này và những thứ khác cho bạn. Tài liệu SQLAlchemy khuyên bạn nên sử dụng thư viện tích hợp thay vì tự làm điều này.

db = SQLAlchemy(app) 

@app.route('/') 
def example(): 
    item = db.session.query(MyModel).filter(...).all() 
    ... 

Cũng lưu ý rằng bạn chỉ nên xác định động cơ, phiên vv một lần và nhập khẩu nó ở nơi khác, chứ không phải xác định lại nó trong mỗi tập tin như mã hiện tại của bạn không.

+0

Đã hoạt động. Cụ thể, tôi đã nhập scoped_session từ sqlalchemy.orm, và sau đó tạo ra một đối tượng "SessionParent" như được mô tả trong hướng dẫn này http://docs.sqlalchemy.org/en/latest/orm/contextual.html –

2

Lấy một gợi ý từ this SO answer Tôi đã tìm kiếm SA tài liệu và phát hiện ra bạn có thể làm điều này:

engine = create_engine('sqlite:////var/www/homepage/blog.db?check_same_thread=False') 

scoped_session là không thực sự phù hợp trong trường hợp của tôi kể từ khi Flask-SQLAlchemy chỉ mất một đối số chuỗi kết nối:

from flask import Flask 
from flask_sqlalchemy import SQLAlchemy 


class Config(object): 
    SQLALCHEMY_DATABASE_URI = 'sqlite:///app.db?check_same_thread=False' 


db = SQLAlchemy() 


def create_app(): 
    app.config.from_object(Config) 
    app = Flask(__name__) 
    db.init_app(app) 
    ... 
Các vấn đề liên quan