使用 flask 框架开发 web 应用,初始化数据库的代码放在哪里最合适?

2015-04-08 11:41:55 +08:00
 caixiexin

python新手,最近使用flask做web应用时,发现个奇怪的问题。
在wsgiapp.py文件中启动flask的web应用,启动前先初始化了全局数据库对象(在另一个db.py文件中),其他蓝图中url处理函数再访问该全局数据库对象,db模块中的engine为None,需要重新初始化一次才能访问数据库。
但是定义在wsgiappp.py的路由函数却能直接访问数据库(也就是已经初始化过),后来尝试在两个地方print hash(db),发现结果不同。
这是什么原因,明明import的是同一个模块。记得之前用自己写的wsgi函数的话,没有这种问题的,flask 在调用run()函数启动webapp后有什么特别的操作吗?
我的python版本是2.7.9

贴下几个主要代码

wsgiapp.py

#!/usr/bin/env python
# -*- coding: utf-8 -*-
from flask import Flask, render_template
from www.api import api_urls
from mvc import db

app = Flask(__name__)
app.config.from_object('config.config')
app.register_blueprint(api_urls.api_bp)
#init db
db.create_engine('dbuser', 'dbpasswd', 'dbname')

@app.route('/')
def index():
    return render_template('index.html')

@app.route('/test')
def test():
    print hash(db)  #与api_urls.py的hash结果不同
    print hash(db.engine) #db.engine不为None
    return render_template('test.html')

if __name__ == '__main__':
    app.run()

api_urls.py

#!/usr/bin/env python
# -*- coding: utf-8 -*-
from flask import Blueprint, render_template, request, jsonify
from www.mvc import db

api_bp = Blueprint('api_bp', __name__)
#不再初始化一次数据库则不能访问
# db.create_engine('dbuser', 'dbpasswd', 'dbname')

@api_bp.route('/blogs')
def blogs_list():
    print hash(db) #与wsgiapp.py的hash结果不同
    print hash(db.engine) #不在文件中初始化的话,db.engine为None
    return 'blogs'

db.py用的是廖雪峰老师python博客教程里的db.py

项目结构大致这样:

└─www
    ├─api --->api_urls.py
    ├─config
    ├─mvc --->db.py
    └─wsgiapp.py

第一次碰到这种坑,找了半天资料无果,不知道大家以前有没有碰到类似的问题?
thanks in advance :)

9261 次点击
所在节点    Python
18 条回复
bcxx
2015-04-08 12:16:42 +08:00
用 factory method 来构造 Flask.App 的实例,然后可以在这个 factory 里面来做初始化操作。

可以参考一下 https://github.com/vtmer/bearychat/blob/master/beary/app.py#L27 这里的例子
Captian
2015-04-08 12:19:17 +08:00
crazyxin1988
2015-04-08 12:20:37 +08:00
推荐 使用 Flask-Script
所有脚本包括初始化的放到单独的manage.py中
clino
2015-04-08 12:40:34 +08:00
kingname
2015-04-08 12:41:26 +08:00
我使用MongoDB,从来不担心遇到这种坑爹问题。
elvis_w
2015-04-08 13:36:02 +08:00
所有业务代码放在一个包里,比如src/app目录,src/app/__init__.py放初始化代码,db对象也在这里初始化:
```python
from flask import Flask
from flask.ext.sqlalchemy import SQLAlchemy

#初始化db
db = SQLAlchemy(app)
app = Flask(__name__)
#导入其他模块
from app import views
```

其他模块比如src/app/view.py
```python
#导入其他插件例如from flask import render_template等
from app import app, db

#剩余代码
```


服务器启动代码放在app的外面,src/run.py
```python
#!flask/bin/python
from app import app
app.run(debug = True)
```
caixiexin
2015-04-08 14:04:54 +08:00
@elvis_w 原来__init__.py 还可以往里面写代码啊。。我一直以为只是用来把文件夹标记成python包的。
zhyu
2015-04-08 14:47:37 +08:00
放在这个web app的__init__.py里啊
caixiexin
2015-04-08 15:31:02 +08:00
@zhyu 我把初始化代码移到www目录的__init__.py下(wsgiapp.py所属的包),结果反过来了,wsgiapp.py里的db模块反而不能访问数据库,其他路由里的却可以了= =||
caixiexin
2015-04-08 15:40:26 +08:00
@Captian 你的例子里的数据库框架,使用SQLAlchemy呢,初始化的时候有传flask的对象进去,也许flask原生支持SQLAlchemy初始化。
我的orm模块是仿照廖雪峰老师的教程写的,不知道怎么搞了= =||
elvis_w
2015-04-08 16:03:50 +08:00
@caixiexin 你在import app时,src/app/__init__.py里的代码就会执行
elvis_w
2015-04-08 16:06:00 +08:00
@caixiexin 在整个项目的__init__.py里初始化db,而不是子模块,你可以参考这个,这个作者的flask教程项目结构挺好
译文: http://www.pythondoc.com/flask-mega-tutorial/
原文: http://blog.miguelgrinberg.com/post/the-flask-mega-tutorial-part-i-hello-world
zhyu
2015-04-08 18:31:24 +08:00
@caixiexin 不知道你目录结构什么样的,稍微贴一部分给你参考一下:

```
|-proj/
|-app/
|-templates/
|-static/
|-lib/
|-utils/
|-__init__.py # initialize db
|-tests/
|-__init__.py
|-test*.py
|-requirements.txt
```
zhyu
2015-04-08 18:32:59 +08:00
缩进都没了。。。
|-proj/ 是一级
|-app/ |-tests/ |-requirements.txt 是二级
剩下的是三级
cbsw
2015-04-08 19:56:00 +08:00
https://exploreflask.com/blueprints.html
感觉这个文档作为官方文档的补充相当不错
caixiexin
2015-04-08 21:45:57 +08:00
@zhyu 感谢! :)
目录树用markdown的代码块语法包起来,缩进就还在了
snopy
2015-04-09 10:42:50 +08:00
fzleee
2015-04-09 10:46:06 +08:00
楼主可以参考这个方案:
https://github.com/fzlee/Tyou/blob/master/app.py
大致的框架不知道是在什么地方找到的,但是挺好用的。初始化DB的代码放在@app.before_first_request 里面

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

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

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

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

© 2021 V2EX