使用FastAPI整合Gradio和Django
大家好,我是每天分享AI应用的萤火君!
经常接触机器学习的同学可能都接触过Gradio这个框架,Gradio是一个基于Python的专门为机器学习项目创建的快速开发框架,可以让开发者快速发布自己的模型给用户测试,目前Huggingface上的机器学习项目都是基于Gradio对外提供服务的。
不过Gradio的目标是机器学习模型的快速演示,真正为用户提供服务时,我们还有很多需要关注的方面,比如用户的鉴权授权、消息通知、静态页面、SEO优化等等,这些使用Gradio有点捉襟见肘,我们还需要使用更加成熟的Web开发框架,比如Django这种。
但是我们初期可能已经用Gradio做了很多的功能,不想重写这些东西,这时候就产生了集成Gradio到其它框架的需求。这篇文章就来分享如何将Gradio集成到成熟的Web框架Django,以方便后来者。
创建Django项目
这里假设我们已经有了一个Gradio的项目,将在这个项目中继续创建一个Django项目。
创建 Django 项目
首先通过 pip 安装 Django:
pip install django
然后在程序的根目录初始化Django项目的一些基础文件:
django-admin startproject myproject
cd myproject
这里的 myproject 需要替换成你的 Django 项目名。
然后我们还要继续创建 Django 应用,应用可以理解为模块,比如项目下有管理模块、用户模块、支付模块和具体的业务单元模块。每个应用都有自己的模型、视图、模板和 URL 路由。
python manage.py startapp myapp
请将myapp改为你的应用名称。
执行完这些命令之后,项目中将会增加一些Django的框架脚本。
创建 Django 页面
有了Django的基础脚本,然后就可以开发Web页面了。
1个页面涉及三个方面:视图、路由和HTML模板,还是以 myapp 为例:
在 myapp/views.py 中创建一个视图:
from django.shortcuts import render
def index(request):
return render(request, 'index.html')
在 myapp/urls.py 中设置 URL 路由到这个视图:
from django.urls import path
from .views import index
urlpatterns = [
path('', index, name='index'),
]
在 myapp/templates/index.html 创建 HTML 模板:
<!DOCTYPE html>
<html>
<head>
<title>Gradio in Django</title>
</head>
<body>
<h1>Welcome to My App</h1>
</body>
</html>
然后我们就可以启动程序,在浏览器访问这个页面了:
uvicorn myproject.wsgi:application --reload
启动程序使用的是 uvicorn工具,myproject是项目的名称,wsgi对应到myproject文件夹下的 wsgi.py。
集成Gradio到Django
准备一个Gradio项目
为了演示,这里准备一个Gradio的程序。
假设文件路径为:gradio/app.py
import gradio as gr
def greet(name):
return f"Hello {name}!"
# 定义 Gradio 接口
demo = gr.Interface(fn=greet, inputs="text", outputs="text")
整合 Gradio 和 Django
现在我们把 Gradio 集成到 Django 中,它们将在同一个进程中运行,对外使用一个端口号。Django 默认通过根目录 / 进行访问,Gradio则通过 /gradio 进行访问。
这里走过一些弯路,有问题的方法就不讲了,直接给出我的方案。
这里还要引入一个框架 FastAPI,我们将使用 FastAPI 来代理对 Gradio 和 Django 的访问,所以其实不是将Gradio集成到Django,这个方法本质上是将 Gradio 和 Django 整合到一起。
打开 myproject/wsgi.py,这是 Django 项目的主文件:
import os
from django.core.wsgi import get_wsgi_application
from fastapi import Request, Response
from starlette.middleware.wsgi import WSGIMiddleware
import gradio as gr
from gradio.app import demo
os.environ.setdefault('DJANGO_SETTINGS_MODULE', 'myproject.settings')
# 创建 FastAPI 应用
app = FastAPI()
# 挂载 Gradio 到FastAPI,注意这个path要和下边中间件中的一致
app = gr.mount_gradio_app(app, demo, path="/gradio")
# 获取 Django 的 WSGI 应用
django_app = get_wsgi_application()
# 注册一个FastAPI中间件,实现
@app.middleware("http")
async def route_middleware(request: Request, call_next):
# 如果路径是 /gradio,则调用call_next,FastAPI框架会交给已经注册的 Gradio程序 处理
if request.url.path.startswith("/gradio"):
return await call_next(request)
# 否则交给Django处理
response = Response()
async def send(message):
if message['type'] == 'http.response.start':
response.status_code = message['status']
response.headers.update({k.decode(): v.decode() for k, v in message['headers']})
elif message['type'] == 'http.response.body':
response.body += message.get('body', b'') # 注意这里用 += 来累积响应体
await WSGIMiddleware(django_app)(request.scope, request.receive, send)
response.headers["content-length"] = str(len(response.body))
return response
这段代码的逻辑也比较简单,先创建FastAPI应用,然后将Gradio程序挂载到FastAPI,这里使用的是Gradio自带的mount_gradio_app方法,然后创建了一个FastAPI的中间件,对不同的路由使用不同的处理。
重点就在这个FastAPI中间件,它可以保证通过 /gradio 访问到Gradio程序,通过 / 访问到 Django 程序。
如果我们使用下面的这种方式来代理 Django,实测将不能通过 /gradio 访问到Gradio程序,无论 Gradio 和 Django 谁先注册。如果你的环境可以,欢迎留下你的各个 package 的版本。
app.mount("/", WSGIMiddleware(django_app))
静态文件的访问
因为静态文件是每个Web程序几乎避不开的,比如图片、css、js等,所以这里特别提下。
在上边的路由中间件中,除了 /gradio 会路由到Gradio程序,其它都会走Django进行处理,静态文件也不例外。
这里假设静态文件放在 static 目录下。
打开 myproject/settings.py,这是 Django 项目的基础设置文件,修改其中静态文件的部分:
STATIC_URL = '/static/'
if DEBUG:
STATICFILES_DIRS = [
os.path.join(BASE_DIR, "static"),
]
else:
STATIC_ROOT = os.path.join(BASE_DIR, 'static')
打开 myproject/urls.py,修改其中的路由定义,增加 re_path 这一行。
urlpatterns = [
re_path('^static/(?P<path>.*)', serve, {'document_root': settings.STATIC_ROOT}),
path('', include('myapp.urls')), # 包含 myapp 的 URL 配置
]
这样可以在调测和生产环境都能正常访问 static 目录下的静态文件,而不用再进行不同的设置。
总结
本文分享了一种整合 Gradio 和 Django 程序的方法,在这种方法下,Gradio 和 Django 可以使用同一个进程,使用相同的端口号对外服务,同时Gradio程序使用子目录 /gradio 进行访问,Django 程序使用根目录 / 进行访问。
因本人对 Django 和 Gradio 的了解有限,文中介绍的方法可能存在瑕疵,请谨慎使用。
关注萤火架构,加速技术提升!
使用FastAPI整合Gradio和Django的更多相关文章
- 一晚上将一个模板整合进了DJANGO
哈哈,说不定,下个图表项目就可以用上呢???:)
- 【Django】 初步学习
这个系列(或者成不了一个系列..)预计会全程参考Vamei様的Django系列,膜一发.说句题外话,其实更加崇拜像Vamei那样的能够玩转生活.各个领域都能取得不小成就的人. [Django] ■ 概 ...
- Nginx + uWSGI 部署Django 项目,并实现负载均衡
一.uWSGI服务器 uWSGI是一个Web服务器,它实现了WSGI协议.uwsgi.http等协议.Nginx中HttpUwsgiModule的作用是与uWSGI服务器进行交换. 要注意 WSGI ...
- day62 django入门(3)
目录 一.无名有名分组的反向解析 1 无名分组的反向解析 2 有名分组的反向解析 二.路由分发 三.名称空间(了解) 四.伪静态(了解) 五.虚拟环境(了解) 六.django版本区别 1 url的区 ...
- Kubernetes v1.16 发布 | 云原生生态周报 Vol. 20
作者:心贵.进超.元毅.心水.衷源.洗兵 业界要闻 Kubernetes v1.16 发布 在这次发布中值得关注的一些特性和 Feature: CRD 正式进入 GA 阶段: Admission We ...
- day02 web主流框架
day02 web主流框架 今日内容概要 手写简易版本web框架 借助于wsgiref模块 动静态网页 jinja2模板语法 前端.web框架.数据库三种结合 Python主流web框架 django ...
- django整合原有的mysql数据库
虽然django适合从零开始构建一个项目,但有时候整合原有的数据库也在所难免,下面以django整合我的mysql作说明. mysql数据是我从京东上抓取的数据,数据表名为jd,演示如图 下面将jd整 ...
- Python第十三天 django 1.6 导入模板 定义数据模型 访问数据库 GET和POST方法 SimpleCMDB项目 urllib模块 urllib2模块 httplib模块 django和web服务器整合 wsgi模块 gunicorn模块
Python第十三天 django 1.6 导入模板 定义数据模型 访问数据库 GET和POST方法 SimpleCMDB项目 urllib模块 urllib2模块 ...
- Django部署以及整合celery
前言 Djngo部署的结构一般都是nginx+uwsgi+python web 一.新建一个Djang项目并合并celery 项目名随便打的..命名规范驼峰啥的别和我扯犊子哈 跑一下,然后我们就有一个 ...
- Python-Django 整合Django和jquery-easyui
整合Django和jquery-easyui by:授客 QQ:1033553122 测试环境 win7 64 Python 3.4.0 jquery-easyui-1.5.1 下载地址1:http: ...
随机推荐
- 三台服务器上离线安装redis哨兵集群,一主二从三哨兵
三台服务器上离线安装redis哨兵集群,一主二从三哨兵 系统安装好gcc环境,(不然编译redis会报错).依旧不知道怎么离线安装gcc环境的可查看CentOS下离线安装gcc环境,图文详细 下载 点 ...
- avdmanager 返回了非零退出代码: 1。
最近做了一次系统还原,很多功能都出现了异常 重装了 Visual Studio 之后创建安卓仿真器的时候遇到问题,说"avdmanager 返回了非零退出代码: 1." 解决思路 ...
- 《重学Java设计模式》笔记——建造者模式
1. 建造者模式可以解决什么问题 我家里有各种形状的瓷器,盘子或者碗.虽然形状不同,但是所用的材料基本上是一样的,比如土.水.釉.彩这些基本的东西. 但是做不同款式的瓷器,方法是不同的.假如说我现在已 ...
- RabbitMQ 基础概念与架构设计及工作机制学习总结
什么是RabbitMQ MQ全称为Message Queue,即消息队列. 它也是一个队列,遵循FIFO原则 .RabbitMQ则是一个开源的消息中间件,由erlang语言开发,基于AMQP协议实现的 ...
- MYSQL——帆软连接报错
2024/07/11 1.报错 2.报错原因 3.解决办法 4.参考 1.报错 错误代码:11300001 数据集配置错误<br>Query:<br>Unknown initi ...
- RabbitMQ接口封装
1.引用 <dependency> <groupId>com.rabbitmq</groupId> <artifactId>amqp-client< ...
- Python 潮流周刊#66:Python 的预处理器(摘要)
本周刊由 Python猫 出品,精心筛选国内外的 250+ 信息源,为你挑选最值得分享的文章.教程.开源项目.软件工具.播客和视频.热门话题等内容.愿景:帮助所有读者精进 Python 技术,并增长职 ...
- python安装和使用常见问题以及解决技巧
1. 快速切换pip版本 pip install pip==22.2 此处22.2代表版本号 , 自动加载压缩包自动切换 2. py窗口程序不能挂代理!!!!!!!!!!!!!!!!!!!!!!!! ...
- k8s-使用Network Policies实现网络隔离
一.需求 Kubernetes 的命名空间主要用于组织和隔离资源,但默认情况下,不同命名空间中的 Pod 之间是可以相互通信的.为了实现更严格的网络隔离,同一套k8s需要根据不同的命名空间进行网络环境 ...
- Windows平台体验StableSwarmUI-0.6.4-Beta经验版
目录 StableSwarmUI install 经验版 StableSwarmUI 配置后端 StableSwarmUI 快捷安装脚本 StableSwarmUI 安装与启动 sd_xl_base_ ...