使用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: ...
随机推荐
- Infinity颜值与实用兼备的新标签页,高效书签管理必选的浏览器扩展
浏览器是我们互联网冲浪的必备平台,但是在使用浏览器的过程中,我们经常会遇到标签页和书签管理的问题.过多的标签页和书签会导致浏览器变得杂乱无章,不利于我们快速查找需要的内容.为了提高我们的工作和学习效率 ...
- css移动端适配方法
一:前端开发的常用单位 1.像素(px) 1.什么是像素(Pixel)? 在前端开发中视口的水平方向和垂直方向是由很多小方格组成的, 一个小方格就是一个像素 例如div尺寸是1 ...
- rk3568 | 瑞芯微平台GPIO引脚驱动编写
最近在玩瑞芯微平台的产品,移植了几个设备的驱动,遇到了一些问题,总结后发现大部分问题都出在了GPIO配置的问题上,写下本篇文章,用来分享一下调试的心得. 有喜欢瑞芯微的朋友,可以加我好友,拉你进群,一 ...
- fofa开放免费教育账号类比专业账号!
用户须知 1.免责声明:本教程作者及相关参与人员对于任何直接或间接使用本教程内容而导致的任何形式的损失或损害,包括但不限于数据丢失.系统损坏.个人隐私泄露或经济损失等,不承担任何责任.所有使用本教程内 ...
- .NETCORE 下使用 NLog
NLog帮助类 1 public enum LogType 2 { 3 [Description("网站")] 4 Web, 5 [Description("数据库&qu ...
- 后缀数组--SA--字符串
SA (Suffix Array) -- 后缀数组 简介 这里明白两个定义: \(SA_i\) : 按字典序排列后大小为 \(i\) 的后缀的后缀头的下标. \(Rank_i\) : 后缀头的下标为 ...
- 守护您的数字资产:API安全的最佳实践
在数字化时代,API(应用程序编程接口)已成为企业与用户.服务与服务之间沟通的桥梁.然而,随着API的广泛应用,安全问题也日益凸显.本文将探讨API安全的重要性,并提供一些实用的安全措施,帮助您保 ...
- Devexpress GridView 单元格输入检验
实现效果 打开设计器 找到CellValueChanged事件 编写代码 private void gvmain_CellValueChanged(object sender, DevExpress. ...
- 即构音视频 Express Flutter SDK 全面支持空安全
Flutter 是一套移动 UI 框架,可以快速在 iOS.Android 上构建高质量的原生用户界面.作为其官方语言 Dart 是类型安全的,当开发者获取变量的时候,编译器可以保证变量的类型,但类型 ...
- 海光 FTPM 运行报错:Fapi_Provision_Finish() ErrorCode (0x00060025) No EK certificate found.
使用的是海光 CPU 提供的基于固件的 FTPM,错误原因是海光没有给 TPM 提供相应的 EK 证书.从而导致Fapi_Provision()接口无法通过证书的校验.关于Fapi_Provision ...