FastAPI: How to render CSS/JS/Images simultaneously in an HTML file?
P粉237125700
P粉237125700 2023-12-11 17:58:49
0
1
602

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粉237125700
P粉237125700

reply all(1)
P粉029057928

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/">
Latest Downloads
More>
Web Effects
Website Source Code
Website Materials
Front End Template