V2EX = way to explore
V2EX 是一个关于分享和探索的地方
现在注册
已注册用户请  登录
推荐学习书目
Learn Python the Hard Way
Python Sites
PyPI - Python Package Index
http://diveintopython.org/toc/index.html
Pocoo
值得关注的项目
PyPy
Celery
Jinja2
Read the Docs
gevent
pyenv
virtualenv
Stackless Python
Beautiful Soup
结巴中文分词
Green Unicorn
Sentry
Shovel
Pyflakes
pytest
Python 编程
pep8 Checker
Styles
PEP 8
Google Python Style Guide
Code Style from The Hitchhiker's Guide
caixiexin
V2EX  ›  Python

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

  •  
  •   caixiexin · 2015-04-08 11:41:55 +08:00 · 9261 次点击
    这是一个创建于 3513 天前的主题,其中的信息可能已经有所发展或是发生改变。

    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 :)

    18 条回复    2015-04-09 10:46:06 +08:00
    bcxx
        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 这里的例子
    Captian
        2
    Captian  
       2015-04-08 12:19:17 +08:00   ❤️ 1
    crazyxin1988
        3
    crazyxin1988  
       2015-04-08 12:20:37 +08:00   ❤️ 2
    推荐 使用 Flask-Script
    所有脚本包括初始化的放到单独的manage.py中
    clino
        4
    clino  
       2015-04-08 12:40:34 +08:00 via Android   ❤️ 1
    kingname
        5
    kingname  
       2015-04-08 12:41:26 +08:00   ❤️ 1
    我使用MongoDB,从来不担心遇到这种坑爹问题。
    elvis_w
        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)
    ```
    caixiexin
        7
    caixiexin  
    OP
       2015-04-08 14:04:54 +08:00   ❤️ 1
    @elvis_w 原来__init__.py 还可以往里面写代码啊。。我一直以为只是用来把文件夹标记成python包的。
    zhyu
        8
    zhyu  
       2015-04-08 14:47:37 +08:00   ❤️ 1
    放在这个web app的__init__.py里啊
    caixiexin
        9
    caixiexin  
    OP
       2015-04-08 15:31:02 +08:00
    @zhyu 我把初始化代码移到www目录的__init__.py下(wsgiapp.py所属的包),结果反过来了,wsgiapp.py里的db模块反而不能访问数据库,其他路由里的却可以了= =||
    caixiexin
        10
    caixiexin  
    OP
       2015-04-08 15:40:26 +08:00
    @Captian 你的例子里的数据库框架,使用SQLAlchemy呢,初始化的时候有传flask的对象进去,也许flask原生支持SQLAlchemy初始化。
    我的orm模块是仿照廖雪峰老师的教程写的,不知道怎么搞了= =||
    elvis_w
        11
    elvis_w  
       2015-04-08 16:03:50 +08:00
    @caixiexin 你在import app时,src/app/__init__.py里的代码就会执行
    elvis_w
        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
    zhyu
        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
    ```
    zhyu
        14
    zhyu  
       2015-04-08 18:32:59 +08:00   ❤️ 1
    缩进都没了。。。
    |-proj/ 是一级
    |-app/ |-tests/ |-requirements.txt 是二级
    剩下的是三级
    cbsw
        15
    cbsw  
       2015-04-08 19:56:00 +08:00
    https://exploreflask.com/blueprints.html
    感觉这个文档作为官方文档的补充相当不错
    caixiexin
        16
    caixiexin  
    OP
       2015-04-08 21:45:57 +08:00
    @zhyu 感谢! :)
    目录树用markdown的代码块语法包起来,缩进就还在了
    fzleee
        18
    fzleee  
       2015-04-09 10:46:06 +08:00
    楼主可以参考这个方案:
    https://github.com/fzlee/Tyou/blob/master/app.py
    大致的框架不知道是在什么地方找到的,但是挺好用的。初始化DB的代码放在@app.before_first_request 里面
    关于   ·   帮助文档   ·   博客   ·   API   ·   FAQ   ·   实用小工具   ·   5168 人在线   最高记录 6679   ·     Select Language
    创意工作者们的社区
    World is powered by solitude
    VERSION: 3.9.8.5 · 30ms · UTC 01:17 · PVG 09:17 · LAX 17:17 · JFK 20:17
    Developed with CodeLauncher
    ♥ Do have faith in what you're doing.