Day 11 实作 create_app

前言

前几天有提到在工厂模式中,我们会用一个函式把全部 app 生起来,今天要实作的就是这个函式,一般习惯会使用 create_appmake_app,我们选择使用前者。

前置作业

如同昨天所说,我们在 create_app 里面会需要初始化一些东西,而这其中包括了资料库。而我们会另外开一个 app/database 来处理资料库的事务,初始化会用到的 db 也不例外,所以我们先来处理一下资料库的相关作业。以下程序码都会放在 app/database 中。

__init__.py

from .models import db

models.py

from flask_sqlalchemy import SQLAlchemy

db = SQLAlchemy()

很明显地,app/database 也是一个 package。我们在 models.py 里面宣告了 db 这个变数,也就是等等我们需要初始化 app 的帮手。接着在 __init__.py 里面把 db 引入,这样等等就可以让别人引入。这个 models.py 是未来用来放资料库结构的地方,但是我们还没到那个部分,就先留着这样就好。

create_app

接下来,我们就来看看该怎麽写吧。我们要把这个函式放在 app/__init__.py 里面。

from flask import Flask
from flask_login import LoginManager
from flask_mail import Mail
from flask_pagedown import PageDown
from flaskext.markdown import Markdown
from .database import db
from .config import configs

login_manager = LoginManager()
mail = Mail()
pagedown = PageDown()


def create_app(env):
    app = Flask(__name__, template_folder="../templates", static_folder="../static")
    app.config.from_object(configs[env])

    login_manager.init_app(app)
    db.init_app(app)
    mail.init_app(app)
    pagedown.init_app(app)
    Markdown(app)

    # Blueprint
    from .main import main_bp

    app.register_blueprint(main_bp)

    from .user import user_bp

    app.register_blueprint(user_bp)

    from .admin import admin_bp

    app.register_blueprint(admin_bp)

    return app

一开始要先注意一下最後面 # Blueprint 後面的程序码,他们目前都不存在,在未来我们会实做到。跟之前说过的一样,基本上他们就是一堆路径,然後分门别类放好,让我们好管理。我们会用 register_blueprint 这个函式把整个蓝图加入 app 里面。我们也可以使用 url_prefix 这个参数来设定这个蓝图的母路径,例如说,我们设定 url_prefix="/auth",那在这个蓝图里面的路径前面都会被冠上 /auth,如果他用的路径是 /login,那 register 过後就会变成 /auth/login。但我们在此专案不会用到,所以先略过。

接着看到最上面的一堆引入,我们引入了 LoginManager,他是 Flask-Login 的核心。也引入了 Mail,他也是一个核心的概念,之後要寄信的时候就会直接找他。PagedownMarkdown 也是相同的概念。再来是刚刚弄好的 db,我们也需要他来初始化。最後还有之前写好的设定档对照表,让我们可以根据环境来决定要用哪个设定。

接下来看到在下面我们把 LoginManagerMailPagedown 和实体化,因为等等会用到这三个实体去初始化。

终於进入 create_app 函式本身了,当然我们需要先弄出 app,但这次的宣告和之前的范例有些不同,多了 template_folderstatic_folder 两个参数,应该可以猜到,他们就是用来指定 jinja 模板目录和 JS、CSS 那些档案的目录的,预设值分别是 templatesstatic,如果不喜欢这个名字也可以自己改掉。这边会需要设定是因为我们这两个目录跟 __init__.py 不是同一层目录,需要往上一层。这个 create_app 接受了 env 这个参数,接下来我们就要用他来汇入之前写的设定档。flask 很好心地有一个函是可以让我们直接从物件汇入,也就是此处的 app.config.from_object,这样一来,我们就可以抓到之前写的设定档了。

最後是初始化的部分,我们需要把五个东西都初始化,这样才能在往後的开发中使用。要初始化的方法是使用他们的 init_app 函式,并以 app 作为参数。但 Markdown 比较特别,他没有 init_app 这个函式,所以要像 db 那样子做,而其他三个其实也可以不要先实体化变成 login_manager,然後在 init_app 的位置初始化,像是 login_manager=LoginManager(app)。但当然 db 没有办法这样做,毕竟他在其他地方就定义好了。

References

Modular Applications with Blueprints


<<:  Day60 (React)

>>:  [Day 11] .Net Task 底层(4)

第一天:目录

目录 09-01-2021 Bonjour! 接下来的 30 天里,每天一点小知识将写下我脑中盘之错...

[Day 21] - 『转职工作的Lessons learned』 - GraphQL (Hasura) - Event Trigger

今天要继续讲一下GraphQL(Hasura)里面的一个小功能 - Event Trigger。 会...

Day 25 - WooCommerce: 验收永丰银行刷卡流程

这个系列的 Day 19 至 Day 24 都是为了完成永丰银行数位金融 API 「丰收款」结合 W...

D6 allauth 采坑日记 Extending & Substituting User model (1)

我本来只是想在注册页面(Signup)增加手机号码(不需简讯验证) 结果被Allauth跟djang...

Day_01: 让 Vite 来开启你的Vue 前言

Hi Da Gei Ho~ 初次见面,我是Winnie~ 我是一位刚转职六个月的菜鸟前端(前身是网页...