使用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: ...
随机推荐
- 19-canvas绘制文字
1 <!DOCTYPE html> 2 <html lang="en"> 3 <head> 4 <meta charset="U ...
- SMU 2024 spring 天梯赛1
SMU 2024 spring 天梯赛1 7-1 种钻石 - SMU 2024 spring 天梯赛1 (pintia.cn) #include <bits/stdc++.h> #defi ...
- ARMv8-A 地址翻译技术之MMU的前世今生
MMU的重要性不言而喻,支撑操作系统之上的各种复杂应用.但在正式讲MMU之前,我们先说说MMU的发展史,因为ARMv8-A的MMU相当复杂,直接切入正题,会显得比较枯燥.废话不多说,咱们马上开始: 一 ...
- Linux内核如何访问另外一个模块的函数和变量 原创
一.问题整理 内核中两个模块,一个A,一个B,A模块中有操作函数,B模块要调用A模块的函数. 二.分析 这是一个驱动工程师经常遇到的一个问题,该问题其实是模块符号导出问题,实现该功能比较简单,借助EX ...
- 关于SQLServer数据库的READ_COMMITTED_SNAPSHOT隔离级别
默认情况下,SQL Server的事务隔离级别是READ COMMITED.刚开始我理解这个模式就是读已经提交的,那也就是说并发一个事务去更新,一个事务查询同一条数据应该是像Mysql.Oracle不 ...
- 在虚拟机CentOS中安装jdk
公众号本文地址:在虚拟机CentOS中安装jdk 本文主要是记录在CentOS中安装新的JDK的过程. 在虚拟机的centos中安装Jdk主要分为三步,第一步上传jdk文件到centos中,第二步解压 ...
- RestoreFormer++: Towards Real-World Blind Face Restoration from Undegraded Key-Value Pairs(IEEE,2023,8)
RestoreFormer++: Towards Real-World Blind Face Restoration from Undegraded Key-Value Pairs(IEEE,2023 ...
- IntelliJ Idea 常用快捷键参照列表
IntelliJ Idea 常用快捷键参照列表 Ctrl+Shift + Enter,语句完成 "!",否定完成,输入表达式时按 "!"键 Ctrl+E,最近的 ...
- ASP.NET Core – Work with Environment (Development, Staging, Production)
前言 这篇讲一讲发布和环境 (development, staging, production) 介绍 我的网站是 host 在 Azure 的 Virtual Machine, 跑 IIS, 没有使 ...
- html4,5 basic
更新: 2021-06-15 游览器 href 和 base href 绝对路径和相对路径 在没有 base href 的情况下 href="/about.html" 就是从 do ...