前天我们写好了 create_app
,但是还没有人呼叫他,今天我们就要来呼叫他 (当然还不能用啦,因为蓝图都没写好)。
这个档案叫做 manage.py
,顾名思义,他就是用来管理的,我们可以用它来操作这个 application 及其附属的资源,像是资料库等等。而他是会用 flask 这个指令来操作 (跟 flask run
同一个),我们预计会加入以下几个指令:
init_db
会把资料库初始化,但如果本来就存在他不会乱动。reset_db
会把资料库整个砍掉再重建。create_user
会用来新增一个使用者,当然也可以透过设定 is_admin=True
来让它变成管理员。事不宜迟,我们就开始吧。但在开始之前我们要先写一下 manage.py
的基本架构。後面我们会执行他,所以也会连带执行到之前的 create_app
,如果想看他正常执行的话,要先把那几行蓝图的程序码注解掉,不然会跑错误,毕竟我们根本没定义过他们。
from os import getenv
from app import create_app, db
app = create_app(getenv("FLASK_ENV"))
@app.shell_context_processor
def make_shell_context():
return globals()
我们在最一开始引入了 getenv
,这是之前很熟悉的函式了。接着还有 create_app
和 db
,後者在今天不会用到,只是先引入留着,之後会用到。
接着我们用 create_app
造出了一个 app
,使用的参数是环境变数 FLASK_ENV
,所以自己要先设定好这个环境变数。
最後三行是 flask 提供的一个可以方便 debug 的小工具,他可以执行 flask 然後开一个 shell 让你跟他互动,可以查现在 app
里面有什麽内容之类的。使用的方式也很简单,用 flask shell
这个指令即可,他就会开一个 shell 给你用。但这时候使用他会喷错误,我们等等还需要设定一个环境变数来处理。要使用这个 shell 是不需要这三行的,flask 本来就可以直接用,他们的用意是把现在的环境直接复制到 shell 里面,让 shell 可以看的资讯更多 (整个 globals()
),他这边用到了 context 这个词,如果深入钻研的话会一直看到他,但在此处就先不提。可以试试看不加这三行,可以很明显地发现如果不加然後在 shell 使用 create_app
会出现未定义。
这时候可能会想,我们根本没有 app.run()
或是类似的函式,那他要怎麽执行?我们需要先设定 FLASK_APP
这个环境变数,它是用来告知 flask 我们的 app
在哪里的。以此处为例,我们需要把它设为 manage.py
,这样 flask 就会知道我们的 app
就放在 manage.py
里面,然後他就会自动自发地执行他。设定完成之後,flask shell
应该就可以使用了,可以尝试看看。
但我们当然不是要执行 shell,我们需要让他真的跑起来让大家都可以用,所以我们就需要用之前用过的 flask run
来让他跑起来,如同上面所述,它会自动去抓 app
然後让他跑起来。
因为这些新指令都是有关资料库的,所以在加入新的指令到 manage.py
之前,我们必须先写好资料库端的函式,基本上就是不要让 db
离开 app/database
。我们需要先多开一个 helper.py
放在 app/database
,然後加入一些函式给外部引入。
from .models import db, Users
def init():
db.create_all()
def reset():
db.drop_all()
db.create_all()
def add_user(username, password, email, introduction=None, is_admin=False):
user = Users(username, password, email, introduction, is_admin)
try:
db.session.add(user)
db.session.commit()
return True
except:
return False
这边加入了三个函式,我们一个一个看。记得也要在 app/database/__init__.py
加入 from .helper import init, reset, add_user
。
init
是用来初始化资料库的,我们使用 create_all
这个函式来帮忙,他会帮我们把资料库的 table 都建好,但如果已经存在的话,他不会把资料删掉。reset
是用来把资料删光光并重新建好资料库的,我们使用 drop_all
和 create_all
,分别会把资料都删光及建立资料库,所以把他们两个一起用就可以达到重设的目的了。add_user
是用来新增使用者的函式,要建立一个使用者很简单,就只要用我们给的参数建立一个 Users
物件即可 (最前面引入了),接下来我们用 try ... except ...
来避免错误,没错误就回传 True
,反之 False
,当然可以做得更细致 (判断使用者名称是否重复等等),但这边就展示性质,不处理其他状况。这边我们使用 db.session.add
来把这个使用者加入到 session
里面,接着再 db.session.commit
把这个变化写入资料库。结束资料库端的函式之後,我们可以看看 manage.py
要怎麽接。要记得最前面需要引入 from app.database import init, reset, add_user
。
@app.cli.command(name="init_db")
def init_db():
init()
@app.cli.command(name="reset_db")
def reset_db():
reset()
@app.cli.command(name="create_user")
def create_user():
username = input("Username: ")
password = input("Password: ")
email = input("Email: ")
is_admin = True if input("Is admin or not (y or n): ") == "y" else False
if add_user(username, password, email, None, is_admin):
print("OK")
else:
print("Failed")
这里我们使用了 app.cli.command
这个装饰器,flask 的这个部分是用 click
实作的,所以会有一些点跟他一样,像是函式名称是 create_user
但要呼叫的时候需要用 create-user
,我自己是习惯把它改掉,使用 name
这个参数。
init_db
的部分基本上就是刚刚的 init
,不管他。reset
也跟刚刚一样,不管他。create_user
我们用 input
的方式让人输入资料,然後加入。这里可以自己加入 email 的判断、密码长度是否过短之类的侦测,这边就不大费周章了。
把他们加入完之後,就可以直接用 flask 来执行,我们可以先 flask init_db
让他初始化资料库,然後 flask add_user
新增一个使用者,没有意外的话应该都可以跑得很顺利。
Command Line Interface
Session Basics
<<: Day13 测试写起乃 - controller test
>>: [Day 1] 全民疯AI系列2.0-机器学习实战手册
Windows复原环境(WinRE)可用於解决Windows 10作业系统不可启动的常见问题。借助W...
陈述式 v.s 表达式 陈述式 JS 的语句类型,用於命令执行指定的一系列操作 最大特徵是不会回传结...
另一系列悲剧..不小心按到上一页.. 感觉这篇还少了点什麽? 如果平常只用过 Leetcode,建...
软功就是什麽都要 Hello 一下之 Hello terraform 这张就会开始动手做了,还没设定...
曾经被系统的地雷,炸得支离破碎 很多好用的应用程序都对Windows不太友善,今天就让你轻松跨越这些...