创建项目
在pycharm中创建一个flask项目,项目目录包含:static、templates、app.py,另外需要提前安装的包如下(如果之前安装过就不用按安装了)
- pymysql
- 安装命令:pip2 install pymysql
- 作用:Python操作数据库的驱动程序
- Flask-SQLAlchemy
- 安装命令: pip3 install flask-sqlalchemy
- 作用:用户flask中使用ORM模型操作数据库
- cryptography
- 安装命令:pip3 install cryptography
- 作用:对密码加密和解密
- Flask-Migrate
- 安装命令:pip3 install flask-migrate
- 作用:用户将ORM模型的变更同步到数据库中
包安装完成后,我们以大型项目为标准完成项目结果,把框架搭建起来
1、 config文件
在studyoa项目根路径下创建一个名叫config.py的Python文件,这个文件用来存储配置项,在项目运行的过程中,会根据环境选择不同的配置,如以数据库连接配置为例,在开发时,可能链接的是开发环境的数据库,在测试时,可能链接的是测试服务器的数据库,而在上线后,则需要更换成线上服务器的数据库,为了满足不同环境下不同的配置,我们在config.py文件中根据环境创建不同的类,分别来实现具体的配置,还有一些在任何环境下都相同的配置项,我们再为其创建一个BaseConfig类,让其他类继承即可,config文件代码如下:
class Baseconfig:
SECRET_KEY = 'your secret key'
SQLALCHEMY_TRACK_MODIFICATIONS = False
#mysql所在的主机名
HOSTNAME = "127.0.0.1"
#MYSQL监听的端口号,默认3306
PORT = 3306
#连接MYSQL的用户名,用户用自己设置的
USERNAME = 'root1234567'
#连接mysql的密码,用户自己设置的
PASSWORD = 'rootroot'
#mysql上创建的数据库名称
DATABASE = 'database'
class DevelopmentConfig(Baseconfig):
SQLALCHEMY_DATABASE_URI = f"mysql+pymysql://{USERNAME}:{PASSWORD}@1{HOSTNAME}:{PORT}/{DATABASE}?charset=utf8mb4"
class TestingConfig(Baseconfig):
SQLALCHEMY_DATABASE_URI = "mysql+pymysql://[测试服务器MySQL用户名]:[测试服务器MySQL密码]@[测试服务器MySQL域名]:[测试服务器MySQL端口号]/[测试数据库名字]?charset=utf8mb4"
class ProductionConfig(Baseconfig):
SQLALCHEMY_DATABASE_URI = "mysql+pymysql://[生产环境服务器MySQL用户名]:[生产环境服务器MySQL密码]@[生产环境服务器MySQL域名]:[生产环境服务器MySQL端口号]/[生产环境数据库名字]?charset=utf8mb4"
接下来在app.py文件中,根据当前环境选择不同的配置类即可,这个以开发环境为例,app.py文件中绑定配置的代码如下:
from flask import Flask
import config
app = Flask(__name__)
#绑定配置文件,直接读取配置文件中的内容
app.config.from_object(config.DevelopmentConfig)
2、exts.py文件
exts.py文件主要是用来存放一些第三方插件的对象,如SQLAlchemy对象、Flask-Mail对象等,创建一个单独的文件用来存放这些对象的目的是为了防止循环引用,以SQLAlchemy对象为例,一般会在app.py文件中通过以下代码创建一个db变量,用于创建ORM模型和进行ORM操作
from flask_sqlalchemy import SQLAlchemy
db = SQLAlchemy(app)
在项目越来越复杂的情况下,为了保证项目的可维护性,通常会把ORM模型放到其他文件中,而创建ORM模型又需要db变量,因此需要从app.py中导入db变量,而为了让ORM模型能够被映射到数据库中,又需要把ORM模型直接或间接导入app.py,这样就产生了循环引用,如下图所示:
stateDiagram-v2
app.py文件 --> ORM模型文件
ORM模型文件 --> app.py文件
循环引用会导致项目运行失败,为了打破循环引用,只要在两者中间加一个exts.py文件,把会引起循环引用 的变量放到exts.py中,然后其他文件都从exts.py中导入,这里还是以db为变量,在添加exts.py后,三者的关系图如下:
stateDiagram-v2
ORM模型文件 --> app.py文件
ORM模型文件 -->exts.py文件
app.py文件 --> exts.py文件
这里使用Flask-SQLAlchemy插件来创建一个SQLAlchemy对象,在exts.py中输入以下代码:
from flask_sqlalchemy import SQLAlchemy
db = SQLAlchemy()
可以看到上述代码在创建SQLAlchemy对象时,并没有传入app,原因是如果使用app.py中的app变量,那么会产生循环引用,次此时可以再回到app.py中,然后导入db变量,再通过db.init_app(app)完成初始化,代码如下:
from flask import Flask
import config
from exts import db
app = Flask(__name__)
#绑定配置文件,直接读取配置文件中的内容
app.config.from_object(config.DevelopmentConfig)
db.init_app(app)
以上代码可以对db变量完成初始化,并且在解决了循环引用的问题,后续其他第三方插件对象,如用于发送邮件的Flask-Mail插件的对象,都可以通过类似的方式实现
3、buleprints模块
为了让项目结构更加清晰,我们通常会使用蓝图来模块化,创建一个blueprints的Python package包,用于存放蓝图,在blueprints下分别创建名为auth.py和qa.py的Python文件,结构如下:
接下来继续完善蓝图,分别在auth.py和qa.py中创建蓝图对象,相关代码如下:
from flask import Blueprint
bp = Blueprint("auth",__name__,url_prefix="/auth")
bp.route("/login")
def login():
pass
from flask import Blueprint
bp = Blueprint("qa",__name__,url_prefix="/")
@bp.route("/")
def index():
pass
2个文件都创建了蓝图对象,并且指定了url前缀,因为qa是首页,所以URL前缀为空,在蓝图对象创建后,还需要在app.py中完成注册,否则是无法使用的,在app.py中注册蓝图代码如下:
from blueprints.qa import bp as qa_bp
from blueprints.auth import bp as auth_bp
app = Flask(__name__)
#绑定配置文件,直接读取配置文件中的内容
app.config.from_object(config.DevelopmentConfig)
db.init_app(app)
#注册蓝图
app.register_blueprint(qa_bp)
app.register_blueprint(auth_bp)
因为在后续开发中,所有前台的视图代码都会放到蓝图中,所以在app.py中遗留的hello_word相关代码,可以直接删除
@app.route("/")
def hello_world():
return "hello world"
4、models模块
为了让项目更加简洁,我们把所有的ORM模型也进行模块化,在项目的根路径下创建一个名为models的python package包,然后在models下分别创建user.py和post.py文件,两个文件分别用来存放与用户和帖子相关的ORM模型,目前为止,项目的结构就已经搭建好了