最新消息:20210917 已从crifan.com换到crifan.org

【已解决】Flask中如何用工厂模式初始化pymongo

Flask crifan 601浏览 0评论
折腾:
【未解决】用蓝图和工厂模式去优化现有Flask项目代码结构
期间,想要把Flask优化代码结构,其中包括转换为工厂模式去初始化Flask的app
其中涉及到PyMongo,而之前的初始化的方式是:
# from flask_pymongo import PyMongo
from gridfs import GridFS
from pymongo import MongoClient
from bson.objectid import ObjectId

purePymongo = MongoClient(
    host=app.config["MONGODB_HOST"],
    port=app.config["MONGODB_PORT"],
    username=app.config["MONGODB_USERNAME"],
    password=app.config["MONGODB_PASSWORD"],
    authSource=app.config["MONGODB_AUTH_SOURCE"]
)
log.info("purePymongo=%s", purePymongo)
# mongoServerInfo = purePymongo.server_info()
# log.debug("mongoServerInfo=%s", mongoServerInfo)

# Pure PyMongo
gridfsDb = purePymongo.gridfs  # Database(MongoClient(host=['xxx:32018'], document_class=dict, tz_aware=False, connect=True, authsource='gridfs'), 'gridfs')
log.info("gridfsDb=%s", gridfsDb)
fsCollection = GridFS(gridfsDb)  # <gridfs.GridFS object at 0x1107b2390>
log.info("fsCollection=%s", fsCollection)
之后就可以用fsCollection了:
if fsCollection.exists(audioFileObjectId):
    audioFileObj = fsCollection.get(audioFileObjectId)
但是现在要把Flask换成工厂模式了,则就不清楚是如何初始化了
pymongo flask factory
python – Flask-PyMongo with application factory and blueprints – Stack Overflow
Failing to instantiate PyMongo objects from @app.before_request · Issue #11 · dcrosta/flask-pymongo
Flask-PyMongo — Flask-PyMongo 2.1.0 documentation
flask-example/application.py at master · allisson/flask-example
dcrosta/flask-pymongo: PyMongo support for Flask applications
python – Access Flask instance when using Flask-Script – Stack Overflow
def create_app(config_name):
    app = Flask(__name__)
    ....
    return app

def create_mongo(app):
    return PyMongo(app)
感觉可以?
但是最外层,没有像:
flask-example/application.py at master · allisson/flask-example
# flask mongoengine

db = MongoEngine()

# flask mail
mail = Mail()


# application factory, see: http://flask.pocoo.org/docs/patterns/appfactories/
def create_app(config_filename):
    app = Flask(__name__)
    app.config.from_object(config_filename)
有db可以去调用了啊
inputlogic/flask-starter: A starter Flask project ready for Heroku, MongoDB and multiple env settings
Failing to instantiate PyMongo objects from @app.before_request · Issue #11 · dcrosta/flask-pymongo
“Thanks for your time on explaining some possible approaches. I took a different approach and defined mongo = PyMongo() at top level in application.py and called mongo.init_app(app) in the factory function.”
好像也是类似的办法,去试试吧
Flask-PyMongo — Flask-PyMongo 2.1.0 documentation
PyMongo 3.7.1 Documentation — PyMongo 3.7.1 documentation
目前先去写成:
import os
from flask import Flask

import logging
from logging.handlers import RotatingFileHandler

# from flask_pymongo import PyMongo
from gridfs import GridFS
from pymongo import MongoClient

from flask_cors import CORS


log = logging.getLogger()


mongo = MongoClient()
fsCollection = None


def create_app(config_object):
    global app, log, api, mongo, fsCollection

    # app = Flask(__name__)
    # app.config.from_pyfile(config_filename)
    #
    # from yourapplication.views.admin import admin
    # from yourapplication.views.frontend import frontend
    # app.register_blueprint(admin)
    # app.register_blueprint(frontend)

    app = Flask(__name__)
    CORS(app)


    # app.config.from_object('config.DevelopmentConfig')
    # # app.config.from_object('config.ProductionConfig')

    app.config.from_object(config_object)

    log = create_log(app)

    log.debug("after load from object: app.config=%s", app.config)
    log.debug('app.config["DEBUG"]=%s, app.config["MONGODB_HOST"]=%s, app.config["FILE_URL_HOST"]=%s',
              app.config["DEBUG"], app.config["MONGODB_HOST"], app.config["FILE_URL_HOST"])

    mongo = create_mongo(app, log)
    log.info("mongo=%s", mongo)
    mongoServerInfo = mongo.server_info()
    log.debug("mongoServerInfo=%s", mongoServerInfo)

    fsCollection = create_gridfs_fs_collection(mongo, log)
    log.info("fsCollection=%s", fsCollection)

    return app


def create_log(app):
    logFormatterStr = app.config["LOG_FORMAT"]
    logFormatter = logging.Formatter(logFormatterStr)

    fileHandler = RotatingFileHandler(
        app.config['LOG_FILE_FILENAME'],
        maxBytes=app.config["LOG_FILE_MAX_BYTES"],
        backupCount=app.config["LOG_FILE_BACKUP_COUNT"],
        encoding="UTF-8")
    fileHandler.setLevel(logging.DEBUG)
    fileHandler.setFormatter(logFormatter)
    app.logger.addHandler(fileHandler)
    # Note: should NOT set StreamHandler here, otherwise will duplicate debug log
    app.logger.setLevel(logging.DEBUG)  # set root log level

    log = app.logger
    log.info("app=%s", app)
    # log.debug("app.config=%s", app.config)

    return log


def create_mongo(app):
    mongo_client = MongoClient(
        host=app.config["MONGODB_HOST"],
        port=app.config["MONGODB_PORT"],
        username=app.config["MONGODB_USERNAME"],
        password=app.config["MONGODB_PASSWORD"],
        authSource=app.config["MONGODB_AUTH_SOURCE"]
    )
    return mongo_client


def create_gridfs_fs_collection(mongo, log):
    # Pure PyMongo
    gridfs_db = mongo.gridfs  # Database(MongoClient(host=['xxx:32018'], document_class=dict, tz_aware=False, connect=True, authsource='gridfs'), 'gridfs')
    gridfs_fs_collection = GridFS(gridfs_db)  # <gridfs.GridFS object at 0x1107b2390>
    return gridfs_fs_collection
待后续调试才知道是否真正工作。
【总结】
Flask改为工厂模式后,mongo的相关代码如下:
app.py
import os

from conf.app import settings
from factory import create_app

app.app_context().push()
if __name__ == "__main__":
    app.run(
        host=settings.FLASK_HOST,
        port=settings.FLASK_PORT,
        debug=settings.DEBUG,
        # use_reloader=False
    )
factory.py
import os
from flask import Flask
...

from gridfs import GridFS
from pymongo import MongoClient
...
from conf.app import settings

from flask import g

################################################################################
# Global Variables
################################################################################
# # log = logging.getLogger() #<RootLogger root (WARNING)>
# log = None
# print("log=%s" % log)
#
# # mongo = MongoClient() # MongoClient(host=['localhost:27017'], document_class=dict, tz_aware=False, connect=True)
# mongo = None
# print("mongo=%s" % mongo)
# fsCollection = None #None
# print("fsCollection=%s" % fsCollection)
#
# celery = Celery() #<Celery __main__ at 0x1068d8b38>
# celery = None
# print("celery=%s" % celery)

################################################################################
# Global Function
################################################################################

def create_app(config_object, init_extensions=True):
    # global log

    # app = Flask(__name__) #<Flask 'factory'>
    app = Flask(config_object.FLASK_APP_NAME) #<Flask 'RobotQA'>
    ...

    # app.config.from_object('config.DevelopmentConfig')
    # # app.config.from_object('config.ProductionConfig')

    app.config.from_object(config_object)
    with app.app_context():
        g.app = app
    
    ...

        if init_extensions:
            register_extensions(app)
            log.info("flask app extensions init completed")

    return app


def register_extensions(app):
    # global log, mongo, fsCollection, api, celery

    log = g.log

    mongo = create_mongo(app)
    g.mongo = mongo
    log.info("mongo=%s", mongo)
    mongoServerInfo = mongo.server_info()
    log.debug("mongoServerInfo=%s", mongoServerInfo)
...

    return app

...

def create_mongo(app):
    # mongo_client = MongoClient(
    #     host=app.config["MONGODB_HOST"],
    #     port=app.config["MONGODB_PORT"],
    #     username=app.config["MONGODB_USERNAME"],
    #     password=app.config["MONGODB_PASSWORD"],
    #     authSource=app.config["MONGODB_AUTH_SOURCE"]
    # )

    if settings.MONGODB_AUTH_SOURCE:
        mongo_client = MongoClient(
            host=settings.MONGODB_HOST,
            port=int(settings.MONGODB_PORT),
            username=settings.MONGODB_USERNAME,
            password=settings.MONGODB_PASSWORD,
            authSource=settings.MONGODB_AUTH_SOURCE
        )
    elif settings.MONGODB_USERNAME and settings.MONGODB_PASSWORD:
        mongo_client = MongoClient(
            host=settings.MONGODB_HOST,
            port=int(settings.MONGODB_PORT),
            username=settings.MONGODB_USERNAME,
            password=settings.MONGODB_PASSWORD,
        )
    elif settings.MONGODB_PORT:
        mongo_client = MongoClient(
            host=settings.MONGODB_HOST,
            port=int(settings.MONGODB_PORT),
        )
    elif settings.MONGODB_HOST:
        mongo_client = MongoClient(
            host=settings.MONGODB_HOST,
        )
    else:
        mongo_client = MongoClient()


    return mongo_client

...
然后其他模块:
resources/files.py
调用mongo用g.mongo:
from flask import g
mongo = g.mongo
fsCollection = g.fsCollection

class GridfsAPI(Resource):

    def get(self, fileId, fileName=None):
        # log = app.logger
        log.info("fileId=%s, file_name=%s", fileId, fileName)

        fileIdObj = ObjectId(fileId)
        log.info("fileIdObj=%s", fileIdObj)
        if not fsCollection.exists({"_id": fileIdObj}):
    
    ...

转载请注明:在路上 » 【已解决】Flask中如何用工厂模式初始化pymongo

发表我的评论
取消评论

表情

Hi,您需要填写昵称和邮箱!

  • 昵称 (必填)
  • 邮箱 (必填)
  • 网址
92 queries in 0.186 seconds, using 23.44MB memory