flask 应该在__init__.py 里初始化数据库连接吗?

2019-03-19 19:12:41 +08:00
 RicardoY
用 flask 做了个小东西,因为只想开一个数据库连接,所以在 __init__.py 里初始化,程序可以运行但是 pycharm 会提示 Unresolved reference。如果这样做是不正确的话...正确的做法是怎么样的呢
3806 次点击
所在节点    Python
17 条回复
jinksw
2019-03-19 19:15:54 +08:00
from flask import g

def get_db():
if 'db' not in g:
g.db = connect_to_database()

return g.db

@app.teardown_appcontext
def teardown_db():
db = g.pop('db', None)

if db is not None:
db.close()

大概是这样吧?
jinksw
2019-03-19 19:16:29 +08:00
http://flask.pocoo.org/docs/1.0/appcontext/
参考 Storing Data 那一节
RicardoY
2019-03-19 19:23:52 +08:00
谢谢您 我去看看
yushenglin
2019-03-19 20:39:30 +08:00
最好一开始就模块化解耦,专门配置一个 settings 文件,里面写连接数据库,而且你可以用 sqlalchemy,连接数据库挺好用的
RicardoY
2019-03-19 21:22:34 +08:00
@yushenglin 我有一个 settings 文件,但是里面只放了数据库的连接信息。如果我在 settings 里连接数据库的话,是在每个用到数据库连接的地方都 import 这个文件吗?
megachweng
2019-03-19 21:39:29 +08:00
secsilm
2019-03-19 21:43:43 +08:00
前段时间刚查过,国外大神们意见都不一致。。。
corvofeng
2019-03-19 22:16:29 +08:00
我是小菜🐔, 不过我不喜欢在__init__.py 里面写东西。 主要原因是在单元测试的时候, 有可能会执行我控制不了的语句
enrolls
2019-03-19 22:56:57 +08:00
使用 @app.before_request 和 @app.teardown_request
装饰器下的函数,在 before_request 设置 _app_ctx_stack.top.db= sqlalchemy.orm.scoped_session()
在 teardown_request 的时候 _app_ctx_stack.top.db.remove()
zxcvsh
2019-03-19 23:51:30 +08:00
搜索:flask 数据库链接持久化
你会看到 #1 #9 相关的东西
RicardoY
2019-03-20 09:42:34 +08:00
@enrolls 谢谢
RicardoY
2019-03-20 09:48:41 +08:00
@zxcvsh 用这个作为关键词搜索出来的内容大多都是 ORM 框架的相关信息
TrickWu
2019-03-20 10:05:30 +08:00
我用的是 flask_sqlalchemy
数据库配置写在 config.py 里面

__init__.py 里面

db = SQLAlchemy()

def create_app(config_name):
app = Flask(__name__)
app.config.from_object(config_name)
db.init_app(app)
return app

然后再主程序里面启动
app = create_app("app.config")
app.run()

大致这样,不过这样有个缺点,就是查询数据库的时候只能在请求上下文中
zxcvsh
2019-03-20 10:09:29 +08:00
@RicardoY ...这返回差异太大了
那你换成 链接池 或 flask g 对象看看
enrolls
2019-03-20 11:53:44 +08:00
因此,初始化数据库连接应该在哪里。
笼统地讲,哪里都可以,看怎么组织代码。关键在于实例化 Flask() 后,在某个 py 文件里面,import 实例,写 2 个函数,把装饰器带上。
有多个函数需要注册,可以按顺序写在一个函数里面,或者看看 before_request_funcs。
teardown_request 同理。
RicardoY
2019-03-20 12:28:06 +08:00
@megachweng 这个真的很有用..!
yuchenyang1994
2019-03-22 13:53:30 +08:00
都说的不太好,g 对象虽然可以,但是不符合 flask 的约定,虽然 flask 对这块管的毕竟宽松,但是使用扩展的约定其实是最好的
example:
```python
class Sqlite:
def __init__(self):
def __init__(self, app=None):
self.app = app
if app is not None:
self.init_app(app)

def init_app(self, app):
app.config.setdefault('SQLITE3_DATABASE', ':memory:')
app.teardown_appcontext(self.teardown)

def connect(self):
return sqlite3.connect(current_app.config['SQLITE3_DATABASE'])

def teardown(self, exception):
ctx = _app_ctx_stack.top
if hasattr(ctx, 'sqlite3_db'):
ctx.sqlite3_db.close()

@property
def connection(self):
ctx = _app_ctx_stack.top
if ctx is not None:
if not hasattr(ctx, 'sqlite3_db'):
ctx.sqlite3_db = self.connect()
return ctx.sqlite3_db

```
这里的 teardown 函数就是 flask 的应用情境的上下文,也就是说,在请求后关闭 sqlite
当然,如果在请求外的时候则:
```python
with app.app_context():
cur = db.connection.cursor()
cur.execute(...)
```
这样的好处就是在请求环境下你可以直接 import 你的 Sqlite 对象用,不需要 request.g.sqllite,初始化也是符合约定
```python
db = Sqlite()
app.init_app(db)
# OR
db = Sqlite(app)
```

这是一个专为移动设备优化的页面(即为了让你能够在 Google 搜索结果里秒开这个页面),如果你希望参与 V2EX 社区的讨论,你可以继续到 V2EX 上打开本讨论主题的完整版本。

https://www.v2ex.com/t/546314

V2EX 是创意工作者们的社区,是一个分享自己正在做的有趣事物、交流想法,可以遇见新朋友甚至新机会的地方。

V2EX is a community of developers, designers and creative people.

© 2021 V2EX