I'm having trouble rendering HTMl files in FastAPI.
main.py file
static_dir = os.path.join(os.path.dirname(__file__), "static") app.mount("/",StaticFiles(directory=static_dir, html=True),name="static") @app.get("/") async def index(): return FileResponse('index.html', media_type='text/html')
When running the above file using uvicorn, I am able to render the HTML file at http://127.0.0.1:8765/, but the static files (such as css, js and images) are not rendered.
index.html: Some code for the HTML file (built with Angular JS)
<link rel="stylesheet" href="styles.87afad25367d1df4.css" media="print" onload="this.media='all'"><noscript> <link rel="stylesheet" href="styles.87afad25367d1df4.css"></noscript></head> <body class="cui"> test <app-root></app-root> <script src="runtime.7f95ee6540776f88.js" type="module"></script> <script src="polyfills.a246e584d5c017d7.js" type="module"></script> <script src="main.4f51d0f81827a3db.js" type="module"></script> </body></html>
File structure:
modulename - static - index.html - styles.87afad25367d1df4.css - runtime.7f95ee6540776f88.js - polyfills.a246e584d5c017d7.js - main.4f51d0f81827a3db.js - main.py - __init__.py
When I open the browser console, it shows like this:
CSS/js should be rendered without containing static, e.g. http://127.0.0.1:8765/styles.87afad25367d1df4.css but it is rendering from http://127.0.0.1:8765/static/styles .87afad25367d1df4.css is loaded in the browser and run.
I'm not sure how to fix this, any help would be greatly appreciated.
Update: Added following code to explain better
main.py
import uvicorn import os import webbrowser from fastapi import FastAPI from fastapi.responses import FileResponse from fastapi.staticfiles import StaticFiles from fastapi.middleware.cors import CORSMiddleware from fastapi.responses import HTMLResponse app = FastAPI( title="UI", description="This is to test", ) app.add_middleware( CORSMiddleware, allow_origins=['*'], allow_credentials=True, allow_methods=["*"], allow_headers=["*"], ) static_dir = os.path.join(os.path.dirname(__file__), "static") app.mount("/",StaticFiles(directory=static_dir, html=True),name="static") def start_server(): # print('Starting Server...') uvicorn.run( "ui.main:app", host="0.0.0.0", port=8765, log_level="debug", reload=True, ) # webbrowser.open("http://127.0.0.1:8765/") if __name__ == "__main__": start_server()
Run this file as a package/module in the test.py file:
from ui import main if __name__ == "__main__": main.start_server()
index.html:
<!DOCTYPE html><html lang="en"> <head> <meta charset="utf-8"> <title>WingmanUi</title> <base href="static/"> <meta name="viewport" content="width=device-width, initial-scale=1"> <link rel="icon" type="image/x-icon" href="favicon.ico"> <link rel="stylesheet" href="styles.87afad25367d1df4.css" media="print" onload="this.media='all'"> </head> <body> This is to test <script src="runtime.7f95ee6540776f88.js" type="module"></script> <script src="polyfills.a246e584d5c017d7.js" type="module"></script> <script src="main.4f51d0f81827a3db.js" type="module"></script> </body> </html>
File structure:
ui - static - index.html - styles.87afad25367d1df4.css - runtime.7f95ee6540776f88.js - polyfills.a246e584d5c017d7.js - main.4f51d0f81827a3db.js - main.py - __init__.py
P粉0290579282023-12-12 16:29:07
First, when using StaticFiles
the html
flag is set to True
so that static files are served (for dynamic web pages, see template instead), for example:
from fastapi import FastAPI from fastapi.staticfiles import StaticFiles app = FastAPI() app.mount('/static', StaticFiles(directory='static', html=True), name='static')
You do not have to define an endpoint to serve the index page because html=True
means running your application in HTML mode; therefore, FastAPI/Starlette will automatically load index.html
— See Starlette DocumentationStatic Files
. Also, if you need additional endpoints, please note that the order in which you define the endpoints within your application matters. . p>
Second, since you have installed a StaticFiles
instance and specified directory='static'
, your static files are expected to be served from that directory. So, all you have to do is move all your static files as well as HTML files into the static
directory. You should then be able to serve static files as follows (assuming you have mounted the StaticFiles
instance to /
, e.g. app.mount('/', ...
):
<script src="someScript.js"></script>
Alternatively, if the StaticFiles
instance is mounted to /static
, such as app.mount('/static', ...)
(see also This answer):
<script src="static/someScript.js"></script>
In your case, the reason why static files are still loaded with static
prefix is that you have installed StaticFiles
instance to /
, like http://127.0.0.1:8000/static/someScript.js
Just because you added
in the HTML document for all relative URL URL. Therefore, you should remove the following line from your HTML file:
<base href="static/">