简体   繁体   English

Flask-RESTful项目结构

[英]Flask-RESTful Project Structure

Here is what I'm working with: 这是我正在使用的:

/myproject
    README.md
    runserver.py
    /myproject
        __init__.py
        api.py
        /resources
            __init__.py
            foo.py
            bar.py
        /common
            __init__.py
            db.py
    /tests
        test_myproject.py

Nothing special here. 这里没什么特别的。 Most of this can be found on the Intermediate Usage page in the Flask-RESTful User's Guide. 其中大部分内容可以在Flask-RESTful用户指南的“ 中级用法”页面中找到。

My concern is with circular imports... 我关注的是循环进口......

api.py api.py

from flask import Flask
from flask_restful import Api

app = Flask(__name__)

from myproject.resources.foo import Foo
from myproject.resources.bar import Bar

api = Api(app)

api.add_resource(Foo, '/Foo', '/Foo/<str:id>')
api.add_resource(Bar, '/Bar', '/Bar/<str:id>')

foo.py foo.py

from flask_restful import Resource
from myproject.common.db import query_db


class Foo(Resource):
    def get(self):
        pass
    def post(self):
        pass

db.py db.py

from flask import g
import sqlite3
from myproject.api import app


def get_db():
    db = getattr(g, '_database', None)
    if db is None:
        db = g._database = sqlite3.connect(app.config['DATABASE'])
        db.row_factory = make_dicts
    return db


def query_db(query, args=(), one=False):
    cur = get_db().execute(query, args)
    rv = cur.fetchall()
    cur.close()
    return (rv[0] if rv else None) if one else rv


@app.teardown_appcontext
def close_connection(exception):
    db = getattr(g, '_database', None)
    if db is not None:
        db.commit()
        db.close()

Clearly, I have introduced a circular import into my project: 显然,我已经在我的项目中引入了循环导入:

api.py -> foo.py -> db.py -> api.py

This isn't a big problem as long as I instantiate the Flask application object before I import my resources (which I do). 只要我在导入资源之前实例化Flask应用程序对象(我这样做),这不是一个问题。 A similar pattern is discussed here (see the Circular Imports section at the bottom of the page). 这里讨论类似的模式(参见页面底部的循环导入部分)。

My question... 我的问题...

Is this a good way to structure a Flask-RESTful project? 这是构建Flask-RESTful项目的好方法吗?

This is the closest SO question on this topic that I could find. 是我能找到的关于这个主题的最接近的SO问题。 I was not satisfied with the answer provided because I don't want to keep my database functions in the top level __init__.py file (or in api.py - where the routes belong). 我对提供的答案不满意,因为我不想将我的数据库函数保存在顶级__init__.py文件中(或者在api.py - 路由所属的位置)。

Here are several other similar SO questions, but they are dealing with import errors (which I am not): 以下是其他几个类似的SO问题,但它们正在处理导入错误(我不是):

Structure Flask-Restful API to use SQLAlchemy 使用SQLAlchemy构造Flask-Restful API

Error importing models when trying to run app 尝试运行应用程序时导入模型时出错

Since your question is largely opinion based, I'm going to suggest what I think would be a better solution :) 既然你的问题基于意见,我会建议我认为更好的解决方案:)

Instead of importing myproject.api.app in db.py , I would create my own module level global variable in db.py to store database configuration: 相反,进口的myproject.api.appdb.py ,我会创造我自己的模块级全局变量db.py存储数据库的配置:

db.py db.py

from flask import g
import sqlite3

_db_config = None # Holds database config

def init(app):
    """ Function must be called to initalize this module """
    global _db_config
    global close_connection
    _db_config = app.config['DATABASE']
    # Manually apply @app.teardown_appcontext decorator
    close_connection = app.teardown_appcontext(close_connection)


def _db_connect():
    if _db_config is None:
        raise Exception('Call init first') # or whatever error you want
    return sqlite3.connect(_db_config)


def get_db():
    db = getattr(g, '_database', None)
    if db is None:
        db = g._database = _db_connect()
        db.row_factory = make_dicts
    return db

....

def close_connection(exception):
    db = getattr(g, '_database', None)
    if db is not None:
        db.commit()
        db.close()

Then in api.py initialize db by calling myproject.common.db.init() 然后在api.py通过调用myproject.common.db.init()初始化db

api.py api.py

from flask import Flask
from flask_restful import Api
from myproject.common import db

app = Flask(__name__)
db.init(app)

....

This way db.py no longer has a dependency on api.py 这样db.py就不再依赖api.py

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM