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 :)
1
bcxx 2015-04-08 12:16:42 +08:00 1
用 factory method 来构造 Flask.App 的实例,然后可以在这个 factory 里面来做初始化操作。
可以参考一下 https://github.com/vtmer/bearychat/blob/master/beary/app.py#L27 这里的例子 |
2
Captian 2015-04-08 12:19:17 +08:00 1
|
3
crazyxin1988 2015-04-08 12:20:37 +08:00 2
推荐 使用 Flask-Script
所有脚本包括初始化的放到单独的manage.py中 |
4
clino 2015-04-08 12:40:34 +08:00 via Android 1
|
5
kingname 2015-04-08 12:41:26 +08:00 1
我使用MongoDB,从来不担心遇到这种坑爹问题。
|
6
elvis_w 2015-04-08 13:36:02 +08:00 1
所有业务代码放在一个包里,比如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) ``` |
7
caixiexin OP @elvis_w 原来__init__.py 还可以往里面写代码啊。。我一直以为只是用来把文件夹标记成python包的。
|
8
zhyu 2015-04-08 14:47:37 +08:00 1
放在这个web app的__init__.py里啊
|
9
caixiexin OP @zhyu 我把初始化代码移到www目录的__init__.py下(wsgiapp.py所属的包),结果反过来了,wsgiapp.py里的db模块反而不能访问数据库,其他路由里的却可以了= =||
|
10
caixiexin OP @Captian 你的例子里的数据库框架,使用SQLAlchemy呢,初始化的时候有传flask的对象进去,也许flask原生支持SQLAlchemy初始化。
我的orm模块是仿照廖雪峰老师的教程写的,不知道怎么搞了= =|| |
12
elvis_w 2015-04-08 16:06:00 +08:00 2
@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 |
13
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 ``` |
14
zhyu 2015-04-08 18:32:59 +08:00 1
缩进都没了。。。
|-proj/ 是一级 |-app/ |-tests/ |-requirements.txt 是二级 剩下的是三级 |
15
cbsw 2015-04-08 19:56:00 +08:00
https://exploreflask.com/blueprints.html
感觉这个文档作为官方文档的补充相当不错 |
17
snopy 2015-04-09 10:42:50 +08:00
|
18
fzleee 2015-04-09 10:46:06 +08:00
楼主可以参考这个方案:
https://github.com/fzlee/Tyou/blob/master/app.py 大致的框架不知道是在什么地方找到的,但是挺好用的。初始化DB的代码放在@app.before_first_request 里面 |