利用Python进行后端开发时,学会的第一个框架就是fastapi,实战多个项目后终于对搭建系统框架有了一些基础认识。
首先,搭建一个新的后端项目时,创建一个项目文档(文件夹),其次当中至少应该涵盖五类文件。
第一类:基础配资文件,即config文件,这类文件通常用于记录一些固定参数,即主要记录一些常量(字符串、数值、字典、列表、元组等),方便后续调参或查参时查阅和修改。在涉及数据库连接的项目中,数据库相关参数也可以一并写入config文件。如果参数很多也可以通过创立文件夹的多个子文件方式将不同类别的固定参数分别开来。
第二类:数据库文件,包括数据库连接文件和数据库操作文件。
数据库连接文件通常是conn_db文件,这类文件通常定义一些数据库连接操作,在Python调用数据库文件时,通常每次调用都需要先连接数据库,完成数据操作后关闭数据库连接,整个流程基本不会有太大变化,因此写成一个固定格式文件会更加方便。
import pymysql
from config import database
def access_db(sql):
# 数据库连接
db = pymysql.connect(host=database['host'], port=database['port'], user=database['user'],
password=database['password'], charset=database['charset'], db=database['db'])
# 获取指针
cur = db.cursor()
# 尝试执行sql
try:
cur.execute(sql)
# 执行失败则返回报错
except Exception as e:
return e
# 获取所有数据
data = cur.fetchall()
# 提交数据库
db.commit()
# 关闭指针
cur.close()
# 关闭数据库连接
db.close()
# 返回数据
return data
在上述代码中,database是在config.py文件中定义的一个字典,通过导入后直接调用字典的键值对而获取数据库连接相关参数。
需要说明三点:
- 在这个数据库连接操作中,用到的是pymysql库,在使用前需要提前配置好;
- 在数据库连接操作中,经常会由于一些人为或客观错误(如sql错误/对换行符识别敏感/多余的注释等问题)导致数据库语句执行失败,因此为了保证项目整体的有效性,通常在sql执行板块使用try...except...语句来保证整体结构的完整性,降低错误损失;
- 在上述命令中,data返回的是获取的所有数据的元组,通常不包含表头,在实际操作中可能存在一些不便利,后续我将会单独讲一章关于利用pandas库完成的数据库相关操作,主要涉及一些dataframe操作。
数据库操作文件(crud.py)通常定义了利用指定数据从数据库增删查改的数据操作命令,针对的是具体数据库表的操作,通常需要定义好指定的sql语句条件后,调用数据库连接命令获取数据即可。如下示例是通过用户名查询指定用户信息的数据库操作语句。
# 查找用户信息
def get_user(username: str, password: str):
sql = f"SELECT * FROM user WHERE username='{ username }' and password='{ password }'"
return access_db(sql)
第三类:模型和对象定义文件,即schemes及models文件。这两类文件通常涉及的是模型中涉及到的类和对象,模型中所定义的类都继承自pydantic库的BaseModel,通过冒号定义数据类型,等号为数据赋初值,如果未传参则为函数传递默认值。以下代码中定义的DataIn即为模型中涉及的接口输入数据类,Union类型表示该参数既可输入时间格式,也可输入字符串格式数据。
from pydantic import BaseModel
from datetime import date
from typing import Union
# 数据类
class DataIn(BaseModel):
platform: str = ''
begin_date_start: Union[date, str] = ''
begin_date_end: Union[date, str] = ''
第四类:接口文件,即api文件。完成基础数据库连接和类、对象的定义后,即可开始定义接口文档。接口文件首先需要调用fastapi接口框架完成接口初始化,其次需要导入文件需要使用的自定义文件及函数。通常在有多个api文件时,每个api文件都是整个系统的一个子类,利用APIRouter类进行初始化即可。在定义接口时声明路由,接口名称,接口参数等信息,定义接口操作,返回接口所需数据,该接口功能即完成。如下示例为定义的一个登录接口,若用户名密码正确,返回"login successed! ",若二者任其一出现错误,则提示 " wrong username or password! "
from fastapi import APIRouter, # Depends, HTTPException, status
import crud
app_login = APIRouter()
# 登录接口
@app_login.post('/login', summary="登录")
def login(username: str, password: str):
user_tuple = crud.get_user(username=username, password=password)
if not user_tuple:
return {"detail": "wrong username or password!"}
else:
return {"detail": "login succeeded!"}
第五类:主文件或运行文件。这个文件是整个架构中最重要的文件,只有定义了运行文件,整个项目才能带动得起来。这个文件重点在于声明fastapi框架和uvicorn运行模块。对app进行初始化操作,说明接口文档名称,描述,版本,接口指向等,同时对定义好的接口完成导入和声明,最重要的是定义uvicorn操作,其中重要的参数包括运行端口,重载、debug模式、线程数量等等。
import uvicorn
from fastapi import FastAPI
from api.api_login import app_login
app = FastAPI(
title='文件分析',
description='数据库操作',
version='1.0.0',
docs_url='/docs',
)
# 跨域
# 1、导包
from fastapi.middleware.cors import CORSMiddleware
# 2、声明一个 源 列表;重点:要包含跨域的客户端 源
origins = ["*"]
# 3、配置 CORSMiddleware
app.add_middleware(
CORSMiddleware,
# 允许跨域的源列表,例如 ["http://www.example.org"] 等等,["*"] 表示允许任何源
allow_origins=["*"],
# 跨域请求是否支持 cookie,默认是 False,如果为 True,allow_origins 必须为具体的源,不可以是 ["*"]
allow_credentials=False,
# 允许跨域请求的 HTTP 方法列表,默认是 ["GET"]
allow_methods=["*"],
# 允许跨域请求的 HTTP 请求头列表,默认是 [],可以使用 ["*"] 表示允许所有的请求头
# 当然 Accept、Accept-Language、Content-Language 以及 Content-Type 总之被允许的
allow_headers=["*"],
# 可以被浏览器访问的响应头, 默认是 [],一般很少指定
# expose_headers=["*"]
# 设定浏览器缓存 CORS 响应的最长时间,单位是秒。默认为 600,一般也很少指定
# max_age=1000
)
app.include_router(app_login, tags=['登录'])
if __name__ == '__main__':
app.add_middleware(CORSMiddleware)
uvicorn.run('run:app', host='0.0.0.0', port=8080, reload=True, debug=True, workers=1)
以上就是一个fastapi项目需要涉及的最主要的文档类型,其中并不是所有文件都是必须要有,可以根据个人习惯进行修改和调整,最重要的是掌握其中涉及的一些主要框架和逻辑。