【Python FastAPI】一篇文章教你从零搭建自己的网站后台!(新手向)

2024/4/2 更新

常见问题
  1. 当所有环境配置完成后,通过本地访问服务端网址时显示"无法访问此网页",且requests出现连接超时报错;
    解决办法: 登录云服务提供商的控制台,让防火墙放行80,443和8000的出入端口即可。

教程说明

本教程利用Python异步编程方法,基于FastAPI和uvicorn库来快速搭建并运行网站后台。由于教程偏向于入门,所以我将介绍网站完整建立过程,并对每个可能的疑惑点进行详细解释;如果你已经有自己的服务器,并且掌握SSH和FTP的连接方法,可以直接跳转至第三步。


一、准备工作

  • 一个有公网IP的服务器
  • 一个域名(可选)
  • SSH终端: Xshell
  • 文件传输: Xftp

1.申请云服务器

根据业务需求的不同, 当然也可以选择租用国外vps,比如:

​ 可能要绑定visa银行卡且收费较高,不过有免费试用额度, 访问外网资源速度很快;

当然也可选择国内云服务器,比如:

​ 注意: 国内服务器和域名都需要进行备案

由于作者刚好有阿里云的学生优惠, 在申请页面按照官方的引导进行身份认证, 于是拿到了一个月免费的服务器;

请注意:服务器的系统镜像请选择发行版Linux,比如Ubuntu、CentOS、Debian等,本教程服务器是阿里云的系统 (应该是从CentOS魔改来的)

2.申请自己的域名

由于阿里云学生申请域名首年一块钱,秉持白嫖到底的态度 我也申请了一个,暂且称为:mydomain.top

选择信息模板

​ 在下单界面需要创建你的信息模版, 认证身份并进行备案,按照官方流程即可。

3.域名解析

当你创建好域名后,前往你的 域名控制台

在域名列表中,你会看到刚刚申请好的域名,此时点击 “解析” —> “新手引导” :

域名列表
域名解析
继续填写域名解析设置:

  • 您的业务需求:

    这里是根据服务器公网IP来确定的,一般都是xxx.xxx.xxx.xxx格式,即IPv4地址;这里我们选择"解析到IPv4地址"就好;

  • 请选择网站域名:

    如果选择设置@主机记录,则通过http://mydomain.top就能访问我们的网站;

    如果选择设置WWW主机记录,则通过http://www.mydomain.top才能访问网站;

    注: 设置成WWW的好处是便于我们后续添加子域名, 比如api.mydomain.top; 这里我们选择WWW记录

  • 请输入网站IP:

    填入之前创建的服务器实例的公网IP就好了

解析设置成功后, 我们可以在cmd中ping一下我们的域名:

ping www.mydomain.top

如果像图中一样能够Ping得通, 就代表我们配置成功了!

Ping命令


二、配置Xshell和Xftp

[Xshell和Xftp](家庭/学校免费 - NetSarang Website (xshell.com)) 这两个软件功能强大、简单易用,且都有家庭和学生免费许可证,比较适合本教程的使用。

Xshell功能: 通过SSH连接我们服务器的终端, 并执行相关命令
这里的“主机”填入服务器公网IP;点击 “连接” 后,会提示你输入用户名和密码,这里根据你服务器的系统账号(一般是root) 和密码, 对应输入即可;出现SSH密钥确认界面时点击保存。
在这里插入图片描述

Xftp功能: 用于本地与远程服务器之间的文件传输, 可以直接复制粘贴文件
(这里填写的信息也与Xshell中一致
Xftp


三、服务器环境配置

到这里为止, 我们已经成功申请了云服务器和域名, 配置好了Xshell与Xftp, 那么接下来开始配置我们的服务器环境。

查看系统python版本:

python --version

本教程使用的Python版本为3.9, 建议Python版本为3.7+

1.创建Python虚拟环境(可选)

教程所使用的FastAPI模块使用了很多Python3.7+的特性,而由于笔者的服务器自带Python3.6版本太低,直接重装可能影响其他系统程序正常工作,故准备建立一个miniconda的虚拟环境。

前往 miniconda主页 查看命令行安装方式:
请添加图片描述

接下来按照官方指引,在Xshell中依此执行下面命令:

# 在root/下新建"miniconda3"目录
mkdir -p ~/miniconda3

# 获取最新miniconda安装包
wget https://repo.anaconda.com/miniconda/Miniconda3-latest-Linux-x86_64.sh -O ~/miniconda3/miniconda.sh

# 执行安装
bash ~/miniconda3/miniconda.sh -b -u -p ~/miniconda3
# 删除安装包
rm -rf ~/miniconda3/miniconda.sh

等待终端完成miniconda的安装后, 执行下面命令初始化conda:

~/miniconda3/bin/conda init bash

接下来创建虚拟环境并命名为myenv, 同时安装Python3.9:

conda create --name myenv python=3.9

等待环境创建完毕, 我们启动这个虚拟环境:

conda activate myenv

此时我们的用户名前缀变成了"(myenv)", 这就代表虚拟环境启动成功了! 这个环境是独立于系统的Python环境的,我们可以在这个环境下安装所需模块。

2.fastapi和uvicorn的安装
# 用conda安装
conda install fastapi
conda install uvicorn
# 或者pip安装
pip install fastapi
pip install uvicorn

三、开始编写网站后台

  1. 我们在系统根目录/ 新建一个 mysite 目录, 用于存放我们的网站文件:
   mkdir /mysite
  1. 在你自己的电脑里, 新建一个文件"server.py", 这将作为网站的后台,之后会放在服务器的 /mysite目录下;

  2. 使用代码编辑器打开"server.py"并导入我们需要用到的库:

   #encoding=utf-8
   import json
   import asyncio
   import uvicorn
   from fastapi import FastAPI, Request
   from fastapi.responses import JSONResponse
   app = FastAPI()	

提示:

  • ASGI: 是一种异步 Web 服务器和应用程序之间通信的标准接口, fastapi和uvicorn都是基于此标准的模块;
  • app: 我们用fastapi实际上是构建了一个ASGI 应用程序, 并将其部署在uvicorn上运行;

​ 注: 考虑到实际开发中网站需要能处理并发的请求, 故我们将采用异步的方式编写后台程序。

  1. 编写处理”GET“请求的函数
   # 处理GET请求
   @app.get("/")
   async def read_root():
   # 读取本目录下的"data.json"文件,将内容返回给客户端
       with open("./data.json", "r", encoding="utf-8") as f:
           data = json.load(f)
       return data

提示:

  • @app.get("/"):是一个修饰器, 用于捕获对server.py所在路径的GET请求;
    换言之,read_root()这个函数就与根目录 /mysite 绑定在一起了,外部访问网址 www.mydomain.top/就等同访问/mysite目录。
    在这里我们简单实现了一个读取数据并返回给客户端的方法。
  1. 编写处理“POST”请求的函数

    这里简单实现了一个json文件上传功能。

   # 处理POST请求
   @app.post("/")
   async def save_data(data: dict):
   # 将客户端发送的内容存储到本目录下,并向客户端发送一条消息
       with open("./data.json", "w", encoding="utf-8") as f:
           json.dump(data, f)
       return {"message": "Data received and saved successfully"}

​ 注: Fastapi支持的请求方法不只GET和POST, 还有PUT,DELETE等, 实现原理与上述相似;

  1. 最后添加程序入口,并设置监听服务器本地的8000端口:

    if __name__ == "__main__":
        uvicorn.run(app, host="0.0.0.0", port=8000)
    
  2. 到这一步,我们的网站后台就写好了, 只需用Xftp将server.py上传至服务器的/mysite目录下即可:

上传server.py


四、为服务器配置Nginx代理

我们知道:http协议走80端口,而https走443端口,但我们的网站后台只监听8000端口;为了将其他端口的请求转发到8000端口上, 我们还需要配置Nginx进行反向代理。

  1. 安装nginx
   # Ubuntu
   sudo apt update
   sudo apt install nginx
   # CentOS
   sudo yum update
   sudo yum install nginx
   
   #验证是否安装成功
   nginx -v
  1. 使用文本编辑器如vim,打开/etc/nginx/nginx.conf:
   sudo vim /etc/nginx/nginx.conf
  1. 找到文件内的server块, 并添加location/字段,完成后如下:

    server {
        listen 80;
        listen [::]:80;
        server_name _;
        root /usr/share/nginx/html;
    
        # Load configuration files for the default server block.
        include /etc/nginx/default.d/*.conf;
    
        error_page 404 /404.html;
        location = /40x.html {
        }
    
        error_page 500 502 503 504 /50x.html;
        location = /50x.html {
        }
        
        location / {
            proxy_pass http://localhost:8000;
            proxy_set_header Host $host;
            proxy_set_header X-Real-IP $remote_addr;
            proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
        }
    }
    
    • proxy_pass 选项用于转发请求至本地的8000端口, 要与我们在server.py中填写的端口一致;

    注意: 点击键盘的"Insert键才能开始编辑文件;完成后点"ESC"键退出编辑模式,然后按":“键输入"wq”,回车后保存并退出文件。

  2. 回到终端界面, 我们来启动nginx :

   # 测试 Nginx 配置是否有误
   sudo nginx -t
   # 启动nginx服务
   sudo systemctl start nginx
  1. 最关键的一步——在终端使用uvicorn启动我们的网站后台,设置监听8000端口:
   # 切换到/mysite路径下
   cd /mysite
   # 启动网站后台
   uvicorn server:app --host 0.0.0.0 --port 8000
这里的`server:app`其实就是代指我们在`server.py`内定义的`app`程序。

当出现下图时就代表网站后台成功启动了 !

uvicorn开启成功


五、网站连通性测试

  1. 我们在自己电脑新建一个"client.py",导入requests库进行测试:
   #encoding=utf-8
   import requests
   
   data = {"message":"success"}
   url = "http://www.mydomain.top"
   
   # 向网站发送一个POST请求
   r = requests.post(url,data) 
   print(r.json())
   # 输出: {"message": "Data received and saved successfully"}
   
   # 向网站发送一个GET请求
   r = requests.get(url)
   print(r.json())
   # 输出: {"message":"success"}
  1. 在浏览器地址栏填入"http://www.mydomain.top",检查是否能打开;

    注意: 如果在国内服务器上搭建了网站, 还需要进行ICP备案,否则会限制网站的访问。

    在服务器端会记录到我们刚刚请求的消息,若出现200 OK字样就代表客户端访问成功了! !
    成功连通


后记——为server.py添加中间件

其实到这里,我们的所有工作都差不多完成了。不过我突然想到, 要是在某段时间内出现大量异常请求如何处理?
为了保证网站正常运行, 我决定为server.py添加新功能——增加一个预处理请求的中间件,对IP在一段时间内的访问次数进行限制

思路:用异步方法实现一个非阻塞计时器,并在达到阈值时对已保存的IP字典进行清除,代码如下:

app = FastAPI()
# 记录IP访问次数的字典
ip_access_count = {}
# 异步任务,用于定期重置IP访问次数
async def reset_ip_access_count():
    while True:
        await asyncio.sleep(3600)  # 设置每小时清除一次
        ip_access_count.clear()
        
# 启动重置IP访问次数的异步任务,添加一个协程
asyncio.create_task(reset_ip_access_count())

# 处理IP限制中间件
@app.middleware("http")
async def ip_limit_middleware(request: Request, call_next):
    client_ip = request.client.host  # 获取请求IP
    # 在IP字典中将该IP访问次数+1
    ip_access_count[client_ip] = ip_access_count.get(client_ip, 0) + 1
    if ip_access_count[client_ip] > 100:  # 当该IP请求次数大于设定阈值时返回403
            return JSONResponse(status_code=403, content={"msg": "Access denied for this IP"})
    response = await call_next(request)  # 将请求交给后面处理(这是Fastapi内置方法)
    return response

拦截成功
可以看到我们的拦截是有效的 !


完整代码

import json
import asyncio
import uvicorn
from fastapi import FastAPI, Request
from fastapi.responses import JSONResponse

app = FastAPI()
# 记录IP访问次数的字典
ip_access_count = {}

# 异步任务,用于定期重置IP访问次数
async def reset_ip_access_count():
    while True:
        await asyncio.sleep(10)
        ip_access_count.clear()

# 启动重置IP访问次数的异步任务
asyncio.create_task(reset_ip_access_count())

# 处理IP限制中间件
@app.middleware("http")
async def ip_limit_middleware(request: Request, call_next):
    client_ip = request.client.host  # 获取请求IP
    # 在IP字典中将该IP访问次数+1
    ip_access_count[client_ip] = ip_access_count.get(client_ip, 0) + 1
    if ip_access_count[client_ip] > 100:  # 当该IP请求次数大于设定阈值时返回403
            return JSONResponse(status_code=403, content={"msg": "Access denied for this IP"})
    response = await call_next(request)  # 将请求交给后面处理(这是Fastapi内置方法)
    return response

# 处理GET请求
@app.get("/")
async def read_root():
    with open("./data.json", "r", encoding="utf-8") as f:
        data = json.load(f)
    return data

# 处理POST请求
@app.post("/")
async def save_data(data: dict):
    with open("./data.json", "w", encoding="utf-8") as f:
        json.dump(data, f)
    return {"message": "Data received and saved successfully"}


if __name__ == "__main__":
    uvicorn.run(app, host="0.0.0.0", port=8000)

阅读至此, 若有不解或有错之处, 欢迎大家留言喔 !
(点个收藏关注,不忘迷路~)

  • 50
    点赞
  • 39
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 5
    评论
FastAPI是一个高性能的Python web框架,使用异步编程方式,提供简洁的API设计,而Django是一个功能丰富的全栈式web框架,适合构建复杂的web应用。接下来我将为你介绍使用FastAPI和Django搭建一个web应用的demo。 首先,我们来看FastAPI的demo应用。在开始之前,我们需要安装FastAPI和相应的依赖,可以使用pip或conda进行安装。在项目目录下创建一个main.py文件,编写以下代码: ```python 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: str = None): return {"item_id": item_id, "q": q} ``` 以上代码创建了一个FastAPI应用,通过访问根路径可以返回一个Hello World的消息,而通过访问/items/{item_id}路径可以返回传入的item_id和查询参数q。运行应用,使用uvicorn运行工具可以启动应用: ``` uvicorn main:app --reload ``` 然后在浏览器访问http://localhost:8000/和http://localhost:8000/items/1?q=test就可以看到相应的返回结果了。 接下来,让我们来看Django的demo应用。同样需要先安装Django。在项目目录下创建一个demo目录用于存放相关代码。进入demo目录后,在命令行中运行以下命令创建一个Django项目: ``` django-admin startproject project_name ``` 创建完项目后,在project_name目录下找到settings.py文件,修改其中的ALLOWED_HOSTS添加本机IP地址。 接着,在project_name目录下,运行以下命令创建一个app: ``` python manage.py startapp app_name ``` 在app_name目录下找到views.py文件,编写以下代码: ```python from django.http import HttpResponse def index(request): return HttpResponse("Hello, World!") ``` 然后,在project_name目录下的urls.py文件中导入app_name中的views,编写以下代码: ```python from django.urls import path from app_name import views urlpatterns = [ path('', views.index, name='index'), ] ``` 接下来,在命令行中运行以下命令启动项目: ``` python manage.py runserver ``` 然后在浏览器访问http://localhost:8000/就可以看到Hello, World!了。 以上就是使用FastAPI和Django搭建一个web应用的demo的示例。两个框架各有优势,可以根据自己的需求选择适合的框架进行开发

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 5
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

Runfreeone

你的鼓励是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值