萌新入门:FastAPI+Python 前后端交互全解析(如何通过Fastapi实现用户登录,注册,查看用户信息项目)
一.简介
(1)FastAPI 是一款现代、轻量、高性能的 Python Web 框架,专门用来快速构建 API(应用程序编程接口,也就是前后端 / 服务间传递数据的 “通道”)。它是近几年 Python 生态中最火的 Web 框架之一,尤其适合萌新快速上手写后端接口 (2)FastAPI 适合做什么:
- 前后端分离项目的后端 API(比如我们之前写的注册 / 登录接口);
- 微服务(拆分后的小服务间的接口);
- 数据接口(比如给前端提供数据库里的商品信息);
- 快速原型开发(想快速验证一个想法,几小时就能搭好后端)
二.FastAPI+Python 前后端交互全解析
作为编程萌新,刚接触前后端交互时总被一堆概念绕晕:FastAPI 怎么写接口?requests 库为啥返回<Response [200]>?后端的Request对象到底是啥?今天就结合实战代码,把这些知识点掰开揉碎,让你彻底搞懂前后端交互的底层逻辑!
1.先搞懂:前后端交互的本质是什么?
用一个餐厅点餐的比喻就能秒懂:
- 前端:你(顾客),负责 “提需求”(比如要一碗牛肉面);
- 后端:厨房(服务器),负责 “处理需求”(煮面、加牛肉);
- HTTP 协议:服务员,负责传递你的需求和厨房的结果;
- 请求:你喊 “服务员,来碗牛肉面”;
- 响应:服务员端来做好的牛肉面(或告诉你 “卖完了”)。
我们写的 Python 前端脚本就是 “顾客”,FastAPI 后端就是 “厨房”,两者靠 HTTP 协议传递数据 —— 这就是前后端交互的核心!
2.项目需求
使用fastAPI实现登录、注册接口
1.提供用户注册接口,当用户名和密码不为空 且 用户名长度大于6,密码长度大于8且包含下划线、字母和数字时,将用户数据保存下来。(注意:不能有相同的用户名)
2.提供用户登录接口,当用户名和密码正确时,提示:欢迎xxx,否则提示:用户名或密码不正确!
3.前后端代码整体思路分析:从功能设计到交互逻辑(完整代码放在文章最后)
作为刚接触Fastapi的初学者,我们使用“FastAPI 后端接口服务 + Python 命令行前端客户端”组合来满足项目需求,以下从后端设计思路 、前端设计思路、前后端交互逻辑三个维度拆解整体思路(以项目注册功能为例)
1.前端代码设计思路
import requestsrequests是 Python 生态中最常用的HTTP 请求库,相当于前端的 “传话员”—— 它帮我们把用户的操作(比如注册、登录)转换成后端能识别的 HTTP 请求,再把后端的响应结果带回来。没有这个库,Python 代码就没法和后端服务器 “对话”。
while True: user_input = input('1、注册\n2、登录\n3、查看\n4、退出\n请输入你要进行的操作:')while True:创建一个无限循环,让程序一直运行,直到用户选择 “退出”(避免用户每操作一次就重新运行一次代码);input(...):在命令行打印操作菜单,等待用户输入指令(1/2/3/4),并把用户输入的内容存到user_input变量里。
这一步是前端和用户交互的 “入口”,相当于餐厅的 “点餐台”,用户告诉点餐员要什么,点餐员再传给厨房。
#前端注册功能 if user_input == '1': user = input("用户名:") password = input("密码:") res = requests.post("http://127.0.0.1:8000/user/register",params={"username":user,"password":password}) result = res.json() print(f"{result["result"]}")user = input("用户名:")/password = input("密码:"):提示用户输入用户名和密码,并存到变量里(收集用户的 “点餐需求”);res = requests.post("http://127.0.0.1:8000/user/register",params={"username":user,"password":password}):requests.post:发送POST 请求到后端注册接口("http://127.0.0.1:8000/user/register");params={"username":user,"password":password}:把用户名和密码作为URL 查询参数拼到请求地址后面(比如http://127.0.0.1:8000/user/register?username=test&password=test_123456),传给后端;res:接收后端返回的响应对象(相当于后端 “做好的菜 + 小票”);
result = res.json():把后端返回的 JSON 格式字符串转换成 Python 字典(解析 “小票” 上的内容);print(f"{result["result"]}"):提取字典里的result字段(后端返回的注册结果),打印给用户看(展示 “菜品” 和 “评价”)
易混淆点:在requests.post("http://127.0.0.1:8000/user/register", params={"username":user,"password":password})中
params是requests库的一个参数,它的核心作用是:将字典形式的键值对,转换成 URL 的 “查询参数”(Query Parameters),拼接到请求 URL 的末尾。
举个具体例子:如果用户输入的用户名是testuser,密码是test_123456,那么params={"username":"testuser","password":"test_123456"}会被转换成:?username=testuser&password=test_123456
最终发送请求的完整 URL 就变成了:http://127.0.0.1:8000/user/register?username=testuser&password=test_123456,将这个经过处理的URL传给后端我们写的注册接口@app.post('/user/register')
elif user_input == '2': user = input("用户名:") password = input("密码:") res = requests.post(urls[1], params={"username": user, "password": password}) result = res.json() print(f"{result["result"]}") elif user_input == '3': res = requests.post(urls[2]) result = res.json() print(f"{result}") elif user_input == '4': break else: print("输入的操作错误请重新输入")以上分别是项目登录、查看、退出功能,里面具体方法与注册功能一致
requests.post返回的是一个Response对象(包含响应状态码、头信息、内容等),直接打印这个对象会显示<Response [状态码]>(200 表示请求成功)。如果你想获取后端返回的数据,需要用res.json()(如果后端返回 JSON)或res.text(如果返回纯文本)解析响应内容。
2.后端代码(FastAPI)设计思路
后端的核心定位是 “提供数据处理接口,维护用户数据,校验业务规则”,整体思路围绕 “接口功能 + 数据管理 + 规则校验” 展开,让我们先来一段一段解析基础的 FastAPI 后端代码:
import uvicorn from fastapi import FastAPI, Request import uvicorn:导入Uvicorn 服务器——FastAPI 是基于 ASGI 协议的框架,需要 ASGI 服务器来 “监听网络请求”(就像餐厅需要服务员站在门口接客),Uvicorn 就是负责这件事的工具。from fastapi import FastAPI, Request:FastAPI:导入 FastAPI 框架的核心类,用来创建后端服务的 “主实例”(相当于搭建餐厅的整体框架);Request:导入 FastAPI 封装的 “请求对象”,用来获取前端发送的请求数据(比如用户名、密码)。
app = FastAPI() 这行代码创建了一个 FastAPI 应用实例,命名为app—— 它是后端服务的 “核心入口”,所有接口、功能都要挂载到这个实例上。可以把它想象成:你开了一家叫app的餐厅,接下来要在餐厅里设置 “注册窗口”“登录窗口” 等业务区域。
user_datas = [{"username": "admin123","password": "admin_123",}] (1)用 Python 列表user_datas模拟 “数据库”(实际项目会用 MySQL/SQLite 等真实数据库,这里为了简化用列表);
(2)列表里预存了一个初始用户{"username": "admin123","password": "admin_123"},用来测试 “用户名重复” 的逻辑;
(3)作用:存储已注册用户的账号密码,后续注册时需要检查用户名是否已存在。
def judgment(username, password): # 条件1:用户名长度大于6 username_valid = len(username) > 6 # 条件2:密码长度至少9位 password_length_valid = len(password) >= 9 # 条件3:密码包含数字 has_digit = any(char.isdigit() for char in password) # 条件4:密码包含字母(大小写均可) has_letter = any(char.isalpha() for char in password) # 条件5:密码包含下划线 has_underline = '_' in password # 条件6:密码只能包含字母、数字、下划线(无其他字符) only_valid_chars = all(char.isalnum() or char == '_' for char in password) # 所有条件都满足则返回1,否则返回0 if username_valid and password_length_valid and has_digit and has_letter and has_underline and only_valid_chars: return 1 else: return 0 (1)定义名为judgment的函数,接收两个参数:username(用户名)和password(密码),作用是校验这两个参数是否符合预设规则。
(2)len()是 Python 内置函数,用于返回对象的长度或元素个数,在我们代码中用来判断用户名和密码是否满足系统对用户的要求
(3)any()是 Python 内置函数,接收一个可迭代对象(如生成器、列表等),只要可迭代对象中有至少一个元素为 True,就返回 True;否则返回 False。
配合字符串方法使用:
char.isdigit():字符串的方法,判断单个字符char是否是数字(0-9);char.isalpha():字符串的方法,判断单个字符char是否是字母(大小写均可,a-z/A-Z);
(4)in是 Python 的成员运算符,用于判断某个元素是否存在于序列(如字符串、列表)中:
'_' in password:检查下划线_是否在密码字符串里,存在则返回 True,否则 False。
(5)all()是 Python 内置函数,接收一个可迭代对象,只有当可迭代对象中所有元素都为 True时,才返回 True;否则返回 False。
char.isalnum():字符串的方法,判断单个字符char是否是字母或数字(即a-z/A-Z/0-9);
代码通过 Python 内置函数(len()/any()/all())、字符串方法(isdigit()/isalpha()/isalnum())和运算符(in/and),实现了对用户名(长度 > 6)和密码(长度≥9、含数字 / 字母 / 下划线、无非法字符)的多维度校验。
# 注册接口 @app.post('/user/register') #注册接口需要获取客户端传来的username和password(通过 URL 查询参数),而这些数据都封装在Request对象里 ——FastAPI 会自动把当前请求的Request实例传给这个参数,你就能通过它拿到请求数据了。 def register(request: Request): username = request.query_params['username'] password = request.query_params['password'] for i in user_datas: if i['username'] == username : return {"result":"注册失败:用户名重复"} if judgment(username, password): user_data = { "username": username, "password": password, } user_datas.append(user_data) print(user_datas) return {"result":f"注册成功:{username}成功注册"} else: return {"result":"注册失败:注册的用户名和密码未满足要求"}(1)@app.post('/user/register')是 FastAPI 的装饰器,作用是:
- 告诉 FastAPI:“当有人用 POST 方法访问
/user/register路径时,就执行下面的register函数”; - 装饰器是 Python 的语法糖,本质是给函数 “加功能”—— 不用装饰器的话,你得手动写代码判断请求方法和路径,麻烦到爆炸!
(2)后端 FastAPI 中的request.query_params,就是专门用来解析 URL 中 “查询参数部分”(即?后面的键值对)的工具。它的底层逻辑是:
- 当后端服务器收到 HTTP (这里指前端代码注册部分)请求时,会先解析请求行中的 URL,提取出
?后面的字符串(比如username=testuser&password=test_123456); - 按照
&分割成多个键值对,再按=分割每个键值对,最终转换成一个字典结构; - FastAPI 把这个字典封装成
request.query_params,所以你能通过request.query_params['username']拿到前端传的用户名。
(3)FastAPI 会自动把函数的return值转换成 JSON 格式(比如return {"result": "注册成功"}会变成{"result":"注册成功"}的 JSON 字符串),再通过 HTTP 响应返回给前端。如果忘记写return,FastAPI 会默认返回 “空响应”—— 前端就拿不到数据了!
if __name__ == '__main__': uvicorn.run("main:app",host="127.0.0.1",port=8000)(1)if __name__ == '__main__':Python 的特殊判断 —— 只有当这个文件被直接运行(比如右键点击 “运行”)时,才执行下面的代码;如果被其他文件导入(比如import main),这部分代码不会执行(避免重复启动服务)。(2)uvicorn.run(...):启动 Uvicorn 服务器,参数说明:"main:app":指定要运行的 FastAPI 应用 ——main是当前文件名(如果文件名叫app.py,这里就是app:app),app是我们创建的 FastAPI 实例名;host="127.0.0.1":指定服务绑定的 IP 地址(127.0.0.1代表 “本机”,只有自己能访问;如果想让局域网其他设备访问,可改为0.0.0.0);port=8000:指定服务监听的端口号(就像餐厅的窗口编号,前端要通过这个端口找到服务)。
3.前后端交互的 “底层逻辑总结”
(1)协议是桥梁:前后端靠 HTTP 协议沟通,就像顾客和厨房靠服务员沟通 —— 都得按 “规矩” 来(比如 POST/GET 方法、JSON 格式);
(2)数据是核心:前端传 “需求数据”(用户名密码),后端返 “结果数据”(注册成功 / 失败),数据格式要统一(JSON 最常用);
(3)校验是保障:前端校验让用户少等,后端校验防 “坏人捣乱”;
(4)状态码是信号:200 = 成功,400 = 用户输错了,500 = 后端代码错了 —— 看状态码能快速定位问题。
三,完整代码展视
我们首先在PyCharm上创建俩个.py文件——main,py,test.py
main.py(项目后端):
import uvicorn from fastapi import FastAPI,Request app = FastAPI() user_datas = [ { "username": "admin123", "password": "admin_123", }] # 用户名、密码判断函数 def judgment(username, password): if len(username)>6 and re.match(r'^(?=.*\d)(?=.*[a-zA-Z])(?=.*_)[a-zA-Z0-9_]{9,}$',password): return 1 else: return 0 # 注册功能 @app.post('/user/register') def register(request: Request): username = request.query_params['username'] password = request.query_params['password'] for i in user_datas: if i['username'] == username : return {"result":"注册失败:用户名重复"} if judgment(username, password): user_data = { "username": username, "password": password, } user_datas.append(user_data) print(user_datas) return {"result":f"注册成功:{username}成功注册"} else: return {"result":"注册失败:注册的用户名和密码未满足要求"} # 登录功能 @app.post('/user/login') def login(request: Request): username = request.query_params['username'] password = request.query_params['password'] if judgment(username, password): for i in user_datas: if i['username'] == username and i['password'] == password: return {'result':f"登录成功:{username}欢迎"} return {"result":f"登录失败:用户名或密码错误"} else: return {'result':'登录失败:用户名或密码输入不正确'} # 查看用户账号信息 @app.post('/user/logout') def logout(): return user_datas # 鼠标右键启动,无需进入终端命令行 if __name__ == '__main__': uvicorn.run("main:app",host="127.0.0.1",port=8000)main.py文件整体运行流程:
当你右键运行后端文件后:先导入模块(uvicorn、FastAPI、Request)→创建 app 实例→初始化模拟数据库 user_datas→定义校验函数 judgment;启动 Uvicorn 服务器,绑定 127.0.0.1:8000,开始 “监听” 前端请求;
当前端发送 POST 请求到http://127.0.0.1:8000/user/register?username=xxx&password=xxx时:FastAPI 匹配到/user/register接口对应的 register 函数;自动封装请求数据为 Request 对象,传入 register 函数;函数内提取参数→遍历检查用户名是否重复→调用 judgment 校验规则→返回 JSON 结果;
当前端发送 POST 请求到http://127.0.0.1:8000/user/login?username=xxx&password=xxx时:FastAPI 匹配到/user/login接口对应的 login 函数;封装请求数据为 Request 对象,传入 login 函数;提取参数→调用 judgment 校验格式→遍历匹配账号密码→返回 JSON 结果;
当前端发送 POST 请求到http://127.0.0.1:8000/user/logout时:FastAPI 匹配到/user/logout接口对应的 logout 函数;直接返回 user_datas 列表作为 JSON 结果;
服务器持续运行,直到你手动停止(比如按 Ctrl+C)。
test.py(项目前端):
import requests while True: user_input = input('1、注册\n2、登录\n3、查看\n4、退出\n请输入你要进行的操作:') if user_input == '1': user = input("用户名:") password = input("密码:") res = requests.post('http://127.0.0.1:8000/user/register',params={"username":user,"password":password}) result = res.json() print(f"{result["result"]}") elif user_input == '2': user = input("用户名:") password = input("密码:") res = requests.post('http://127.0.0.1:8000/user/login', params={"username": user, "password": password}) result = res.json() print(f"{result["result"]}") elif user_input == '3': res = requests.post('http://127.0.0.1:8000/user/logout') result = res.json() print(f"{result}") elif user_input == '4': break else: print("输入的操作错误请重新输入")test.py文件整体运行流程:
- 程序启动→导入 requests→定义后端接口列表→进入无限循环;
- 打印菜单→用户输入指令→按指令分支处理:
- 注册 / 登录:收集账号密码→发 POST 请求→解析响应→展示结果;
- 查看:直接发请求→解析用户列表→展示;
- 退出:结束程序;
- 若输入错误,提示后重新等待输入。
前后端联动整体运行流程总结
当你先启动后端文件,再启动前端文件后:后端:导入模块→创建 app 实例→初始化数据库→定义校验函数→启动 Uvicorn 监听 8000 端口;前端:导入 requests→定义接口列表→进入 while 循环打印操作菜单;
当用户在前端输入 “1” 选择注册时:前端接收用户名 / 密码→发送 POST 请求到后端注册接口(带 URL 参数);后端接收请求→校验用户名唯一性→校验规则→返回结果;前端解析 JSON 响应→打印注册结果→回到菜单循环;
当用户在前端输入 “2” 选择登录时:前端接收用户名 / 密码→发送 POST 请求到后端登录接口(带 URL 参数);后端接收请求→校验格式→匹配账号密码→返回结果;前端解析 JSON 响应→打印登录结果→回到菜单循环;
当用户在前端输入 “3” 选择查看时:前端发送 POST 请求到后端 logout 接口;后端返回所有用户数据;前端解析 JSON→打印用户列表→回到菜单循环;
当用户输入 “4” 时,前端跳出循环结束运行,后端保持监听直到手动停止。
前后端数据传递类型
后端代码里,返回的是 Python 的字典(dict)或列表(list):
- 注册 / 登录接口返回的是
{"result": "..."}(Python 字典); /user/logout接口返回的是user_datas(Python 列表)。
FastAPI 会自动将这些 Python 原生类型(dict、list、str、int 等)序列化为 JSON 字符串,再通过 HTTP 响应返回 —— 你不需要手动转 JSON,FastAPI 帮你做了序列化。
前端代码里,用res.json()方法,会把后端返回的 JSON 字符串反序列化为 Python 的字典或列表(这一步叫 “反序列化”)。比如:
- 后端返回的 JSON 字符串
"{\"result\":\"注册成功...\"}",经res.json()解析后,变成 Python 的dict类型:{"result": "注册成功..."}; - 后端返回的用户列表 JSON 字符串,解析后变成 Python 的
list类型:[{"username": "admin123", "password": "admin_123"}]。