Python flask project configuration and dynamic registration blueprint

I haven't done flask development for a long time. Now I mainly want to share with you some experience summaries about the previous flask project development, I hope it will be helpful to everyone!
The initialization file in the flask startup project generally includes steps such as initializing the app, initializing the configuration config, and registering the blueprint!
The most satisfactory way is to manually add two lines of code to the initialization file for blueprint registration every time a new module is added!

Project configuration file config.py:

The SECRET_KEY must be set, and preferably a random number, to prevent csrf, otherwise a Must provide secret_key to use csrf error warning will appear!

# -*- coding: utf-8 -*-
import os

class Config(object):
    SECRET_KEY = 'wwzgYXYPI/ytEfA4wP1W5KucP21vaDaiusGaO5OlaOBw5O1Bg1f3nmg+G0VkauQPQEodiI4AKXF05rLPNmvquFYC'

    @staticmethod
    def init_app(app):
        # staticmethod可以在类不需要实例化时调用方法
        pass

class DevConfig(Config):
    DEBUG = True
    SQLALCHEMY_ECHO = True
    CELERY_BROKER_URL = 'redis://localhost:6379/0'
    CELERY_BACKEND_URL = 'redis://localhost:6379/0'
    SQLALCHEMY_DATABASE_URI = "mysql+pymysql://root:123456@ip:port/dev_db"


config = {
    
    'development': DevConfig}

Generate a random string for SECRET_KEY:
import os, base64

def create_key(length):
	random_str = os.urandom(length)
	byte_ret = base64.b64encode(random_str) # 生成byte类型字符串: b'Easpoammc+/'
	result = byte_ret.decode('unicode_escape')
	return result

if __name__ == '__main__':
	create_key(66)

# 测试结果:wwzgYXYPI/ytEfA4wP1W5KucP21vaDaiusGaO5OlaOBw5O1Bg1f3nmg+G0VkauQPQEodiI4AKXF05rLPNmvquFYC
The initialization __init__.py file is as follows:
from flask import Flask, redirect, url_for
from config import config
from flask_sqlalchemy import SQLAlchemy
from .extensions import celery
from flask_login import LoginManager, login_required, current_user


# 实例化数据库对象
db = SQLAlchemy()
login_manager = LoginManager()
login_manager.session_protection = 'strong'
login_manager.login_view = 'auth.login'


def create_app(config_name='development'):
    '''
    1: 创建一个app应用程序
    2: 把配置对象传递给所创建的app
    '''
    app = Flask(__name__)
    app.config.from_object(config[config_name])

    # 将app中的配置文件应用到db中
    db.init_app(app)
    celery.init_app(app)
    login_manager.init_app(app)
    login_manager.login_message = '请先登录'

    from app.auth import auth as auth_bp
    app.register_blueprint(auth_bp, url_prefix='/auth')

    from app.main import main as main_bp
    app.register_blueprint(main_bp, url_prefix='/main')

   	# 登录后默认跳转页
    @app.route('/')
    @login_required
    def index():
        return redirect(url_for('main.index'))

    return app

Obviously, if there are few developed functions, the above kind of registration for blueprints one by one is not a big problem. Once the project business becomes more and more complicated, a large piece of registration code will appear in the above method, and the same is done. It is neither beautiful nor concise, so you can use batch registration to optimize the code and encapsulate the dynamic registration blueprint function!

  • method one
import importlib
import os

def auto_register_blueprint(app):
    path = os.path.dirname(os.path.abspath(__file__))
    base_file = path.split('\\')[-1]
    for filename in os.listdir(path):
        file_path = os.path.join(path, filename)
        if not os.path.isdir(file_path):
            continue
        if not os.path.exists(os.path.join(file_path, '__init__.py')):
            continue
        auto_blueprint = importlib.import_module(f'{base_file}.' + filename).__dict__[filename]
        app.register_blueprint(auto_blueprint, url_prefix=f'/{filename}')
  • Way two
from werkzeug.utils import import_string
import os

def auto_register_blueprint(app):
    path = os.path.dirname(os.path.abspath(__file__))
    base_file = path.split('\\')[-1]
    for filename in os.listdir(path):
        file_path = os.path.join(path, filename)
        if not os.path.isdir(file_path):
            continue
        if not os.path.exists(os.path.join(file_path, '__init__.py')):
            continue
        auto_blueprint = import_string(f'{base_file}.' + filename + ".__init__:" + filename)
        app.register_blueprint(auto_blueprint, url_prefix=f'/{filename}')

The optimized initialization __init__.py file is as follows:

def create_app(config_name='development'):
    '''
    1: 创建一个app应用程序
    2: 把配置对象传递给所创建的app
    '''
    app = Flask(__name__)
    app.config.from_object(config[config_name])

    # 将app中的配置文件应用到db中
    db.init_app(app)
    celery.init_app(app)
    login_manager.init_app(app)
    login_manager.login_message = '请先登录'

    auto_register_blueprint(app)

    # 登录后默认跳转页
    @app.route('/')
    @login_required
    def index():
        return redirect(url_for('main.index'))

    return app
Project startup management file manage.py
# -*- coding: utf-8 -*-
from flask_script import Manager, Shell, Server
from app import create_app, db


app = create_app('development')
manager = Manager(app)

def make_shell_context():
    return dict(app=app, db=db)


manager.add_command('shell', Shell(make_context=make_shell_context))

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

The basic files of the above projects are configured, the project can be started, enter the shell command:

python manage.py shell

Project startup command, where host and port are optional parameters:

python manage.py runserver --host 0.0.0.0 --port 8888

The blueprint configuration of a single submodule, for example, for the account module blueprint registration, create a new __init__.py file under the account file, as follows:

from flask import Blueprint

account = Blueprint('account', __name__)

from .forms import *
from .views import *
from .models import *

Guess you like

Origin blog.csdn.net/Lin_Hv/article/details/113112527