FastApi的初体验

随着python的发展,也出现了越来越多的框架,如Django,Falsk,Bottle框架等,FastApi就是其中之一,同时,也能够进行异步操作,async/await,这里借用官网的一句话FastAPI 是一个用于构建 API 的现代、快速(高性能)的 web 框架,使用 Python 3.8+ 并基于标准的 Python 类型提示。具体的特性也在官网上有所讲述,首先使用的话需要有python环境,可以去官网上进行安装,python环境搭建还是较为简单的,直接去python官网进行安装就可以了,安装好后,同时也需要python的编辑器,这里我使用的是PyCharm,可以自行去官网下载,在搭建好使用环境后,同时也不能忘记去配置环境变量,这里具体的配置方式可以自行搜索

这里直接使用

pip install fastapi

来安装fastapi,以及服务器:

arduino 复制代码
pip install "uvicorn[standard]"

这里我们可以使用PyCharm自带的工程创建来创建一个fastapi的工程,同时可以去选择使用虚拟环境去创建,可以避免无法管理相关的python包

然后通过

css 复制代码
uvicorn main:app --reload

来启动我们的服务器

如果是用过PyCharm创建的话,我们的根路径下的入口文件就会有:

python 复制代码
from typing import Union

from fastapi import FastAPI

app = FastAPI()


@app.get("/")
def read_root():
    return {"Hello": "World"}


@app.get("/items/{item_id}")
def read_item(item_id: int, q: Union[str, None] = None):
    return {"item_id": item_id, "q": q}

如果没有的话,大家可以自行创建一下,并且fastapi有继承自swagger文档,可以通过访问 http://127.0.0.1:8000/docs来自行查看api文档,同时也可以自行设置相关的配置,下一张再来详细的讲一下,数据库的配置以及如何通过orm模型操作数据库

​ 2.FastAPI如何链接数据库 ​

这里使用的是mysql,基本的mysql环境搭建大家可以自行去网上搜索,这里不再说明,接下来直接上代码:

1、首先需要安装tortoise-orm,我们是通过orm模型去操作数据库,使用orm模型操作的好处是不需要使用sql命令,直接使用函数进行操作,能有效的防止sql注入式攻击,操作也会简洁一些,

pip install tortoise

2、接下来需要在入口文件进行导入和挂载:

ini 复制代码
from tortoise.contrib.fastapi import register_tortoise
register_tortoise(
    app,
    db_url='mysql://用户名:密码@数据库ip:数据库端口/用户名',
    modules={"models": ["models.user", "models.article"]},
    generate_schemas=True,
    add_exception_handlers=True,
)

这里的路径我给大家标注了一下,自己配置的时候要记得更换哦

剩下的配置分别是:

  • generate_schemas:是否自动创建数据库和表结构,这里设置为 True,表示在启动应用时如果相关表不存在,则会自动创建。
  • add_exception_handlers:是否添加 Tortoise ORM 的异常处理器

这里的app,是我们的fastapi主程序

3、接下来要说明一下modules了,这里的modules是我们存放模型的地方,是使用类来进行创建的表:

ini 复制代码
from tortoise import Model, fields



class Article(Model):
    userid = fields.IntField()
    id = fields.IntField(pk=True)
    title = fields.CharField(max_length=30)
    content = fields.CharField(max_length=9999)
    createTime = fields.DatetimeField(auto_now_add=True)
    updateTime = fields.DatetimeField(auto_now=True)

这样我们在启动当前服务的时候,就会通过tortoise,来创建一张表了

然后我们就可以这么去操作:

less 复制代码
@app.post("/announce", summary='发布文章')
async def article_announce(body: Announce):
        await Article(userid=token, title=body.title, content=body.content).save()
        return JSONResponse(status_code=status.HTTP_200_OK)
    

这就是最简单的往数据库中添加数据了,这里的Announce类呢是:

python 复制代码
from pydantic import BaseModel, Field
class Announce(BaseModel):
    title: str = Field(examples=["标题"])
    content: str = Field(examples=["内容"])

这里我们需要从pydantic模型库中去导入我们需要继承的类,以及属性

​ 3.FastAPI------token验证 ​

其实fastapi自身对于token就有验证的,不过这里需要对用户输入的用户名和密码的参数限制为username,password,这对于我们来说有些限制了,比如我们在写微信小程序,或者APP登录时,我们一般不会去使用这种格式,并且在数据库中存入的参数形式也不一致,这样子对于我们来说就不是很有友好了,所以我们这里选择使用token,在使用的时候,我们需要先导入jwt,使用jwt来进行加密以及验证:

pip install jwt

然后需要使用加密字符,这里我没有使用他们的标准生成密钥方式,这里可以使用:

ini 复制代码
import os
key = os.urandom(32)

这种方式来进行密钥的生成,规范的生成模式还是以官网的那种方式去生成

ini 复制代码
def jwt_token(data: dict, expires_delta: timedelta):
    jwt_dict = data.copy()
    expired = datetime.utcnow() + expires_delta
    jwt_dict.update({'exp': expired})
    token = jwt.encode(jwt_dict, key, algorithm="HS256")
    return token

这里我们先不说这个函数的,我们先来说

ini 复制代码
jwt.encode(jwt_dict, key, algorithm="HS256")
# 这里的jwt_dict 是我们的加密数据以及过期时间等数据组成的字典,这里的key,是我们的加密密钥,然后
# algorithm是加密方式
python 复制代码
datetime.utcnow() + expires_delta 
# 这一步是格式化时间 在此之前,我们需要导入 
from datetime import datetime, timedelta

然后我们再回到函数中,data为加密数据,是我们需要再登录时去处理的用户数据,然后expires_delta为过期时间,然后我们再回到我们的接口中去

ini 复制代码
@api.post("/login", summary='用户登录')
async def user_login(body: Register):
    res = await User.filter(userName=body.userName)
    if len(res) == 0:
        return JSONResponse(status_code=status.HTTP_405_METHOD_NOT_ALLOWED,
                            content=APIResponse(405, None, "用户不存在").set_api_dict())
    else:
        md5password = password_md5(body.passWord)
        password = await User.get(userName=body.userName)
        if md5password == password.passWord:
            token = jwt_token({"userID": password.id}, timedelta(days=3))
            return JSONResponse(status_code=status.HTTP_200_OK, content=APIResponse(200, {"token": token}, "登录成功")
                                .set_api_dict(), headers={"Set-Cookie": "X-token=Bearer "+token})
        else:
            return JSONResponse(status_code=status.HTTP_405_METHOD_NOT_ALLOWED,
                                content=APIResponse(405, None, "用户名或密码有误").set_api_dict())

这里的APIResponse是我自己定义的一个函数,用来处理返回数据的,大家这里可以自行忽略,同时我这里也使用了md5加密的一个形式,在前后端交互中,前端也可以处理加密,后端也可以,这个可以大家自行沟通,并且我这里也只是提供一个逻辑而已 ,后续我们再讲一下token的验证如何处理

4.FastAPI中的token验证 ​

在fastapi中,我们可以通过依赖注入的方式,来对一个接口进行token的验证,来判断在数据库中是否有这个用户,我们需要先申明一个函数用来做token的验证操作:

python 复制代码
import jwt
import os
from fastapi import Header
from typing import Optional
from .APIResponse import APIResponse
from fastapi.responses import JSONResponse
from fastapi import status
from jwt.exceptions import InvalidSignatureError, ExpiredSignatureError, DecodeError
key = os.urandom(32)
async def verify_jwt(token: Optional[str] = Header(None)):
    if token is None:
        return JSONResponse(status_code=status.HTTP_405_METHOD_NOT_ALLOWED,
                            content=APIResponse(405, None, "用户未登录").set_api_dict())
    else:
        try:
            res = jwt.decode(token, key, "HS256")
            return res['userID']
        except InvalidSignatureError as e:
            # 无效签名验证
            return JSONResponse(status_code=status.HTTP_403_FORBIDDEN,
                                content=APIResponse(403, None, "无效的用户签名").set_api_dict())
        except ExpiredSignatureError as e:
            # 签名过期验证
            return JSONResponse(status_code=status.HTTP_401_UNAUTHORIZED,
                                content=APIResponse(401, None, "用户签名已过期").set_api_dict())
        except DecodeError as e:
            return JSONResponse(status_code=status.HTTP_401_UNAUTHORIZED,
                                content=APIResponse(401, None, "错误的签名").set_api_dict())

在这里我们将错误类型进行了导入,其实应该还有一部分其他类型的错误,我这里只是简单使用了一下,然后指定token类型为str,并且导入Header,将从这里获取我们的token,然后并对token解码进行验证,这样,就完成了我们的token验证函数

这里我也将我申明的APIResponse为返回给前端的数据:

python 复制代码
import json


class APIResponse:
    def __init__(self, code, data=None, message=None):
        self.code = code
        self.data = data
        self.message = message

    def set_api_dict(self):
        api_dict = {
            "code": self.code,
            "data": self.data,
            "message": self.message
        }
        return api_dict

然后在接口中使用:

python 复制代码
from fastapi import  status, Depends
from models.user import User
from fastapi.responses import JSONResponse
from utils.APIResponse import APIResponse
from utils.JWT import jwt_token, verify_jwt
@api.get("/logout", summary="用户注销")
async def user_logout(token: str = Depends(verify_jwt)):
    if type(token) is int:
        res = await User.get(id=token)
        await res.delete()
        return JSONResponse(status_code=status.HTTP_200_OK, content=APIResponse(200, None, "用户注销成功").set_api_dict())
    else:
        return token

在这里我们需要导入Depends,将我们的验证函数进行注入至接口,这样fastapi在前端进行请求的时候会自动运行这个函数verify_jwt,这样就是一个简单的token验证了。

相关推荐
pcplayer25 分钟前
WEB 编程:使用富文本编辑器 Quill 配合 WebBroker 后端
前端·后端·delphi·web开发·webbroker
xuchengxi-java3 小时前
SpringBoot Kafka发送消息与接收消息实例
spring boot·后端·kafka
OEC小胖胖3 小时前
MyBatis系统学习(四)——MyBatis的关联映射和缓存机制
java·后端·学习·缓存·mybatis·web
firepation3 小时前
SpringBoot - 基于 Java的超市进销存系统
java·spring boot·后端
冒泡的肥皂4 小时前
java表格识别PaddleOcr总结
java·后端·百度飞桨
尘浮生4 小时前
Java项目实战II基于Java+Spring Boot+MySQL的房屋租赁管理系统的设计与实现
java·开发语言·数据库·spring boot·后端·mysql·spring
一朵忽明忽暗的云4 小时前
【SSM-Day2】创建SpringBoot项目
java·spring boot·后端
Pandaconda4 小时前
【计算机网络 - 基础问题】每日 3 题(十三)
开发语言·经验分享·笔记·后端·计算机网络·面试·职场和发展
customer085 小时前
【开源免费】基于SpringBoot+Vue.JS服装商城系统(JAVA毕业设计)
java·vue.js·spring boot·后端·开源