前言
在上一篇文章中荔枝已经梳理了Flask的基础语法,但是想要靠这些东西来写一个项目是远远不够的噢,我们还需要一个更加清晰的项目逻辑来搭建一个Flask后端项目框架,在真实的项目开发中,我们还需要了解如何搭建数据库,如何管理高效管理代码,如何使自己写的东西可维护性更好。
在本篇文章中,荔枝会基于自己之前学习的时候跟着的一个项目来梳理一下在项目的开发中我们应该怎么去写Flask后端。
目录
前言
一、项目工程结构
二、项目核心文件详解
2.1 入口文件——manager.py
2.1.1 Flask_script拓展
2.1.2 manager.py中的flask_script
2.2 Flask全局变量文件——application.py
2.3 配置文件——base_setting.py
2.4 HTTP配置文件——www.py
三、数据库——MySQL
3.1 ORM框架
3.2 MySQL驱动——mysqlclient
总结
一、项目工程结构
我们首先来看看整个项目的代码结构
- 其中manager.py是整个项目的主要入口文件,在终端或者是服务器上挂起整个项目的时候,我们只需要运行入口文件即可。
- config是我们的基本配置文件夹,其中base_setting.py就是我们的项目基本配置,里面包含着整个项目在开发环境或者是生产环境中的共同配置;
- www.py一般是蓝图在应用上的注册以及统一拦截器的预加载;
- application.py文件时我们整个项目的核心文件,它实例化了一个Flask类,同时定义了一个Application类并继承Flask类并重写其方法和配置,使得我们的项目更加灵活;
- web文件夹里面的文件是我们整个项目的逻辑和外衣,里面的视图函数和前端模板共同构成了我们整个项目的功能;
- common就是公共的方法或者是公共类;
- requirement.txt是项目的拓展文件,我们可以在命令行终端中使用如下命令直接安装项目拓展
pip install -r requirements.txt
开发环境和生产环境
开发环境就是我们在开发项目的时候用到的配置环境,通常在这个环境中我们都会开启debug模式,方便我们调试代码,开发环境一般为了方便配置较全并且配置比较随意,显得比较杂;而生产环境则是整个项目在上线运行时的环境,使用的资源一般都是优化后的,更精致,更轻量化。
讲到这里,大家有没有发现一个问题?
你会发现,我们在上一篇文章中讲到Flask默认的模板文件是放在和项目文件同级父目录下的templates文件夹中,为什么这里是放在web里面呢?如果你发现了这个问题,那么说明你前面至少学进去了哈哈哈
这里是因为荔枝在application.py文件中对Application类继承的Flask类中的__init__()方法进行重写,通过实例化Application类的时候给它传递参数更改静态模板的配置路径,这里其实我们就可以将配置文件用上了,注意要用绝对路径哈。
二、项目核心文件详解
2.1 入口文件——manager.py
二话不说,直接上代码:
# 入口方法
from application import app, manager
from flask_script import Server
import www
##web server
manager.add_command("runserver", Server(host="127.0.0.1", port=app.config['SERVER_PORT'], use_debugger=True, use_reloader=True))
def main():
manager.run()
if __name__ == '__main__':
try:
import sys
sys.exit(main())
except Exception as e:
import traceback
traceback.print_exc()
在入口文件中,我们需要将Flask实例文件即application,py和HTTP模块文件导入入口文件,在这里我们使用了flask_script这个拓展,flask_script拓展在Flask中使用是比较多的,这里为了更好的配置数据库,我们使用了flask_script来自定义命令。
2.1.1 Flask_script拓展
可以直接安装
pip install Flask-Script
也可以在requirements.txt中写上拓展名,执行如下命令:
pip install -r requirements.txt
介绍
Flask-Script是一个可以让你的命令行支持自定义命令的工具,可以为Flask程序添加一个命令解释器,使得我们可以使用app.run()来传参,可以在命令行中指定运行的ip和端口,也可以在启动命令中修改配置。
用法
我们可以在application.py文件中从flask_script引入Manager类,并把Flask实例化对象以参数的形式传递给Manager类。这时候我们的启动命令就是manager.run()。
from flask_script import Manager
from flask import Flask
app = Flask(__name__)
manager = Manager(app)
if __name__ == "__main__":
manager.run()
2.1.2 manager.py中的flask_script
Server类以支持我们的自定义拓展。在这里我们用add_command()来自定义命令名称和拓展配置。
现在把Server类的源码摆出来分析一下哈哈:
def __init__(self, host='127.0.0.1', port=5000, use_debugger=None,
use_reloader=None, threaded=False, processes=1,
passthrough_errors=False, ssl_crt=None, ssl_key=None, **options):
self.port = port
self.host = host
self.use_debugger = use_debugger
self.use_reloader = use_reloader if use_reloader is not None else use_debugger
self.server_options = options
self.threaded = threaded
self.processes = processes
self.passthrough_errors = passthrough_errors
self.ssl_crt = ssl_crt
self.ssl_key = ssl_key
在__init__()方法中我们可以直接看出参数的默认配置,那我们就可以根据项目来修改我们的参数值啦,是不是很简单呐。这里提一下,use_reloader配置的是当我们修改代码后会不会自动重新加载,use_debugger就是是否开启调试模式。
这时候我们的启动命令就会变成:
python manager.py runserver
2.2 Flask全局变量文件——application.py
同样的我们也来看这个项目中的代码:
# 封装类
from flask import Flask
from flask_script import Manager
from flask_sqlalchemy import SQLAlchemy
import os
class Application(Flask):
def __init__(self, import_name, template_folder=None, root_path=None):
super(Application, self).__init__(import_name,template_folder=template_folder, root_path=root_path,static_folder=None)
self.config.from_pyfile('config/base_setting.py')
self.config.from_pyfile('config/local_setting.py')
db.init_app(self)
# os.getcwd() --- 获取根目录
# super().__init__() --- 继承父类的方法
db = SQLAlchemy()
app = Application(__name__, template_folder=os.getcwd() + "/web/templates/", root_path=os.getcwd())
manager = Manager(app)
'''
函数模板
'''
from common.libs.UrlManager import UrlManager
app.add_template_global(UrlManager.buildStaticUrl, 'buildStaticUrl')
app.add_template_global(UrlManager.buildUrl, 'buildUrl')
app.add_template_global(UrlManager.buildImageUrl, 'buildImageUrl')
先来看看Application类的__init__()方法,那么这里我们使用了super()方法来使Application类继承并重写Flask类的构造方法———__init__()方法。我们可以看一下Flask类__init__()方法的源码:
def __init__(
self,
import_name,
static_url_path=None,
static_folder="static",
static_host=None,
host_matching=False,
subdomain_matching=False,
template_folder="templates",
instance_path=None,
instance_relative_config=False,
root_path=None,
):
从Flask类的__init__()方法中的参数我们可以看出在Flask默认就配置了静态模板和静态资源的路径 ,我们可以利用重写父类的方法来将我们的配置参数传进去,实现自定义。
如何实现加载配置文件
self.config.from_pyfile('config/base_setting.py')
使用的配置文件中的配置时往往采用如下命令:
app.config['NAME']
当然了,使用配置文件的前提是要先把配置文件导入该程序中哈哈哈。
注意:
db变量的声明要在app变量之前,这个db变量就是我们操作数据库的变量。
2.3 配置文件——base_setting.py
老规矩,上代码:
SERVER_PORT = 8999
DEBUG = True
SQLALCHEMY_ECHO = True
#数据库配置
SQLALCHEMY_DATABASE_URI = 'mysql://root:123456@127.0.0.1/food_db'
SQLALCHEMY_TRACK_MODIFICATIONS = False
SQLALCHEMY_ENCODING = "utf8mb4"
#分页配置
PAGE_SIZE = 5
PAGE_DISPLAY = 10
# 状态配置
STATUS_MAPPING = {
"1":"正常",
"0":"已删除"
}
'''
过滤url
'''
IGNORE_URLS = [
"^/user/login",
"^/api"
]
API_IGNORE_URLS = [
"^/api"
]
IGNORE_CHECK_LOGIN_URLS = [
"^/static",
"^/favicon.ico"
]
# 上传方法的配置
UPLOAD = {
'ext':['jpg','gif','bmp','jpeg','png'],
'prefix_path':'/web/static/upload/',
'prefix_url':'/static/upload/'
}
# 域名-图片上传地址的配置
APP = {
'domain':'http://127.0.0.1:8999'
}
这里要注意的就是数据库的配置,在开发的时候debug模式要记得打开,其它的配置就更具自己的项目需求咯。这里的过滤地址是过滤url是记录一些无需校验登录的路径,在后面的文章我会详细讲讲。
2.4 HTTP配置文件——www.py
from web.controlers.index import route_index
from web.controlers.user.user import route_user
from web.controlers.static import route_static
from web.controlers.account.account import route_account
from web.controlers.finance.Finance import route_finance
from web.controlers.food.Food import route_food
from web.controlers.member.Member import route_member
from web.controlers.stat.Stat import route_stat
from web.controlers.api import route_api
from web.controlers.upload.Upload import route_upload
from application import app
'''
统一拦截器
'''
from web.interceptors.AuthInterceptor import *
from web.interceptors.ApiAuthInterceptor import *
'''
蓝图功能,对所有的url进行蓝图功能配置
'''
app.register_blueprint(route_index, url_prefix="/")
app.register_blueprint(route_user, url_prefix="/user")
app.register_blueprint(route_static, url_prefix="/static")
app.register_blueprint(route_account, url_prefix="/account")
app.register_blueprint(route_finance, url_prefix="/finance")
app.register_blueprint(route_food, url_prefix="/food")
app.register_blueprint(route_member, url_prefix="/member")
app.register_blueprint(route_stat, url_prefix="/stat")
app.register_blueprint(route_api, url_prefix="/api")
app.register_blueprint(route_upload, url_prefix="/upload")
在这个文件中,我们主要实现的是蓝图在视图函数上的注册和应用,使用app对象中的register_blueprint()函数实现蓝图注册功能,设置好相关功能块的根路径,同时将视图函数文件导入www.py文件。
三、数据库——MySQL
在flask中,我们有多种选择来实现数据存储服务。在这里我选用的是Flask-SQLAlchemy这个插件来搭建我们MySQL数据库的ORM框架。
3.1 ORM框架
ORM(Object-relational mapping),对象映射关系,是一种用来解决面向对象与关系型数据库不匹配现象的技术。说白了,ORM技术就是将关系型数据库中的数据表映射成相应编程语言下的类对象,实现了面向对象封装,这个类我们一般称为模型类。数据库中的字段和类型对应着相应编程语言下类的属性和类型。同时,一个模型类就对应着一张表,这些模型类文件就会被我们放在项目的model文件夹中。
优点
1.ORM允许我们通过模型类来自动生成数据表,使得开发效率更高;
2.数据访问更加轻量化,不用写太多的sql查询语句;
3.支持面向对象封装。
安装flask-sqlAlchemy
首先以管理员身份运行命令行终端,依次执行以下命令:
pip install flask-sqlalchemy
安装mysqlclient
pip install mysqlclient
如何搭建
#在Flask实例化文件中导入SQLAlchemy
from flask_sqlalchemy import SQLAlchemy
app = Flask(__name__)
#声明数据库的配置
app.config['SQLALCHEMY_DATABASE_URL'] = 'mysql://......'
db = SQLAlchemy(app)
裸露的sql查询实例:
from flask import Flask
from flask_sqlalchemy import SQLAlchemy
from sqlalchemy import text
app = Flask(__name__)
#声明数据库的配置
app.config['SQLALCHEMY_DATABASE_URL'] = 'mysql://......'
db = SQLAlchemy(app)
@app.route("/")
def test():
sql = text("SELECT * FROM 'user'")
result = db.engine.execute( sql )
for row in result:
app.logger.info(row)
return "Test"
3.2 MySQL驱动——mysqlclient
其实不论是Flask、Django还是Tornado框架,它的数据库底层还是基于python实现,那么我们就需要一个数据库驱动来帮我们操作数据库,在python我们可以使用MySQL驱动来实现数据库操作,比如:mysqlclient、pymysql。
安装
直接pip安装:
pip install mysqlclient
使用txt文件安装:
pip install -r requirement.txt
在这里,作为初学者,在一般的练手项目中,基本上MySQL就已经符合要求了。但数据库的类型和不同数据库的作用还是要有所了解,后端开发跟数据库是分不开的。
总结
在这篇文章中,荔枝主要是从项目工程的角度入手梳理了在项目的实际开发中我们应该怎么去将代码的架构搭建出来。当然了,可能在真实工作中或者生产环境中需要考虑的会更多哈哈哈,项目的结构会更加复杂、数据库的选型也不一定就是MySQL,有可能会选择非关系型的数据库,因项目而异吧。总之不管初学者还是已经学了一段时间的小伙伴,荔枝还是建议大家去找项目做一遍,这样的收获会比你啃文档更多哈哈哈,写这几篇文章也是想着梳理一下之前学习的东西,复盘好后再去学习新的内容,总之大家一起加油哈哈哈哈哈。
码字不易呐,举起小爪爪,给荔枝一点小奖励吧~~~