自学内容网 自学内容网

PdServer(pythonAPI服务框架):快速开始

PdServer是一个pythonAPI服务器,我相信当你在看到这篇内容时,你是真的需要一个可以实现各项功能的python API服务器,以实现为你的其它业务提供能力的需求。毕竟目前python拥有足够多的开源库,例如我们的爬虫,情感分析。

项目整体代码结构,我们已经在上一篇讲解,不太清楚可以先去了解一下。

图片

在这篇文章中,我们将以实现一个login接口来进行演示,login非常重要,因为要获取token,这需要我们在每一个业务接口中带上,实现对用户的鉴权,否则不能执行。

在这个过程中,我们需要:

  • 路由中接收一个"login"请求;

  • 查询数据库进行鉴权;

  • JWT生成token;

  • 将userinfo与token返回;

这个过程,我们基本上跑通了流程,当然其它的一些我们会在会续的文章中分享。

  • 配置端口

SERVER_PORT作为监听端口,其源于config.ini配置项,由于需要在初次运行后,才会自动生成config.ini,因此,你可以在初始化配置中修改端口,如果你已经运行过,就会自动生成这个config.ini,可以在config.ini中去修改端口。

修改初始配置如下图所示,在PdBaseKits-tools-ini中,找到initialSysConfig方法可以看到初始配置。

图片

initialSysConfig()
#配置端口 server = {        'port' : 8062,    }

(代码中初始化配置)

如果已经有了配置文件,在界面的系统设置中可以看到文件路径:

图片

图片

(config.ini)

  • 配置路由

为了可以接收一个请求,我们需要配置我们的路由。如果你对路由没有概念,你可以把它认为就是服务器处理请求的入口。

  • 路由前缀

这不是必须的,你可以复用我们的配置,但如果你希望修改的话,你可以在server-APP下server.py完成了服务器的启动配置。路由前缀就是请求“http://localhost:8062/v1/api/trigger/login”中的“/v1/api/trigger/”部分。

图片

其中'prefix'定义了路由的前缀,可以根据你自己的业务需求进行修改,同时可以看到,刚刚修改的port最终在这里使用。

def register_blueprints(_app):    from server.router import router    _app.include_router(router.router, prefix="/v1/api/trigger")

def run(host, port):    _app = init_app()    uvicorn.run(_app, port=port, host=host)

  • 路由配置

为了让服务器可以处理我们的请求,我们需要配置我们的路由,在server-router目录下。

图片

打开这个文件可以配置一个login请求处理,如下所示。

@router.post("/login", response_model=UserLoginResponse)async def login(body: User):    return {"user": 'zyy', "id": "12", 'token': 'testteststesttest', 'nickname': 'dean', 'headUrl': 'i.png'}

将其设置为post请求,'/login'是路由,body是request,我们定义为User结构,response_model是响应的结构,定义为UserLoginResponse。我们将结构体的定义在schema.py中。

图片

class User(BaseModel):    user: str    pwd: str
class UserLoginResponse(BaseModel):    user: str    id: int    token: str    nickname: str    headUrl: str

你可以根据自己的业务需求进行修改调整。

数据返回我们通过return完成,这需要保证返回JSON与response_model指定类型是一致的,否则会报错。

  • 密码解密

我们配置了AES的加解密,我们默认你的登陆使用了AES进行加密,因此,我们需要先进行解密。

我习惯于将业务代码脱离router,因此,在我们的server-service下,我们可以写我们的业务代码。

图片

在这里我新建了一个login方法,其对pwd进行解密。

class klingService:
    def login(self,userId, pwd):        try:            pwdDecrypt = aesECBDecrypt(pwd)        except Exception as e:            return False        print("pwdDecrypt:"+pwdDecrypt)                #默认登陆成功        return True
      

现在路由中的代码也需要引用这个login方法。

midService = klingService()
    logging.info("login ["+body.user+"],["+body.pwd+"]]")
    if midService.login(body.user, body.pwd):               return {"user": 'zyy', "id": "12", 'token': "testtesttest", 'nickname': 'dean', 'headUrl': 'i.png'}    else:        return ""

和刚才的返回默认值相比,我们多了login的调用,但返回数据依然是模拟的。下一步我们将通过id,pwd去DB中校验,其相关的代码我们也会写到这个service中。

  • 数据库访问

我们并没有像mybatis那样实现ORM,当然python也有自己的orm库,但我们并没有实现,这主要是因为我们的python应用,目前还没有需要大量的数据库访问,你可以自己去实现。相关代码在PdBaseKits-sql中。

图片

DbBase.py实现了基础的连接和关闭,数据库的账号密码在config.ini中配置,我需要自建一个UserRegDao.py来实现用户表的读取,这个类需要继承DbBase类。在这里,我们需要自已来拼接一个SQL语句。

​​​​​​​

import loggingfrom typing import Union
from PdBaseKits.exceptions.exceptions import SqlConnectErrorfrom PdBaseKits.sql.DbBase import DbBasefrom entity.UserInfo import UserInfo

class UserRegDao(DbBase):    def __init__(self):        logging.info("UserRegDao")        super().__init__()

    # 析构方法    def __del__(self):        super().__del__()
    def chkUserInfo(self, userName:str, pwd:str)->Union[UserInfo,bool]:        sql = "select * from userinfo where username='"+userName+"' and password='"+pwd+"'"        print(sql)        data, c = self.exeStockSql(sql)        if not data:            return False
        for r in data:            id=r[0]            userName = r[1]
        userInfo = UserInfo(id, userName)        return userInfo


我们在这里创建了一个UserInfo类,用来承接用户信息数据:

​​​​​​​

class UserInfo():    def __init__(self,id,user):        self.id = id        self.user = user
    id:int    user: str

然后,我们将这个dao层的调用写到service中,如下所示:

​​​​​​​

class klingService:
    def login(self,userId, pwd):        try:            pwdDecrypt = aesECBDecrypt(pwd)            user = UserRegDao()        except Exception as e:            return False        print("pwdDecrypt:"+pwdDecrypt)
        return user.chkUserInfo(userId, pwdDecrypt)

我们看到,和之前相比,多了chkUserInfo()方法的调用。这样,我们就是真实的通过数据库来判断用户是否存在。

同时,我们的router中也可以获取用户信息了,我们需要改写一下,不再使用默认数据。

​​​​​​​

@router.post("/login", response_model=UserLoginResponse)async def login(body: User):    midService = klingService()
    logging.info("login ["+body.user+"],["+body.pwd+"]]")
    userInfo = midService.login(body.user, body.pwd)    if userInfo:        return {"user": userInfo.user, "id": userInfo.id, 'token': "testtest"ken, 'nickname': 'dean', 'headUrl': 'i.png'}    else:        return ""

  • JWT生成token

在前面的代码中,我们只需要在router中login方法下,增加两行生成token的方法,并用这个真实生成的token去替代之前的“testtesttest”数据。

​​​​​​​

@router.post("/login", response_model=UserLoginResponse)async def login(body: User):    midService = klingService()
    logging.info("login ["+body.user+"],["+body.pwd+"]]")
    userInfo = midService.login(body.user, body.pwd)    if userInfo:        accessTokenExpires = timedelta(minutes=ACCESS_TOKEN_EXPIRE_MINUTES)        accessToken = create_access_token(data={"userName": body.user,'id': userInfo.id}, expires_delta=accessTokenExpires)
        return {"user": userInfo.user, "id": userInfo.id, 'token': accessToken, 'nickname': 'dean', 'headUrl': 'i.png'}    else:        return ""

好了,我们的login到这里,已经从最初的返回一条默认数据,到现在完成了全部的功能。

  • 运行

在完成router/service/UserRegDao后,打开serverMain.py文件,点击pyCharm右上角的运行当前文件,启动了我们的UI,然后点击“启动服务”按钮。在终端上看到如下提示说明启动成功!

图片

我们通过apifox调试一下:

请求链接如下,这里的vi/api/trigger就是我们前文所说的前缀:

http://localhost:8062/v1/api/trigger/login

POST请求内容在body中,使用json:

图片

然后发送请求:

图片

完美!接口顺利运行,请求获得了响应!

  • 总结

在今天的内容中,我们分享了使用PdServer实现了一个login接口。在这个过程中学习了使用数据库,解密,token生成等。整个过程十分简单,你只要按步骤一步一步来即可。如果你有任何的问题、建议,欢迎与我们联系。私信不经常看,欢迎直接加微信(cdszsz)!或关注公众号:AIGC中文站!认准咱们的头像。


原文地址:https://blog.csdn.net/zyysql/article/details/142286815

免责声明:本站文章内容转载自网络资源,如本站内容侵犯了原著者的合法权益,可联系本站删除。更多内容请关注自学内容网(zxcms.com)!