Ga naar hoofdinhoud

HTML in bestanden

Tot nu toe schrijf je HTML als strings in Python. Bij een grote pagina raak je daarin het overzicht kwijt, dus zet je de HTML voortaan in een eigen bestand.

Mappenstructuur​

Maak een map static met daarin een map pages. In static komen alle bestanden die de browser nodig heeft: straks ook je CSS en je afbeeldingen. Hoe je mappen verder groeien, zie je bij Projectstructuur.

je-project/
├── main.py
└── static/
└── pages/
└── home.html

HTML bestand maken​

Maak static/pages/home.html:

static/pages/home.htmlgaat zoals hij is naar de browser
<!DOCTYPE html>
<html>
<head>
<title>Home</title>
</head>
<body>
<h1>Welkom!</h1>
<p>Dit is een HTML bestand, geen Python string.</p>
</body>
</html>

FileResponse gebruiken​

Zet FileResponse bij de imports, en vervang je endpoint voor / uit Je eerste endpoint door een versie die home.html teruggeeft. Laat je andere endpoints staan. Zo ziet de bovenkant van je main.py eruit; regel 2 is de import die verandert:

main.pydraait op de server
from fastapi import FastAPI
from fastapi.responses import FileResponse, HTMLResponse

app = FastAPI()

@app.get("/")
async def home():
return FileResponse("static/pages/home.html")
  1. Regel 2:

    FileResponse komt naast HTMLResponse, want /pagina en /styled gebruiken die nog. Met FileResponse stuur je geen string terug, maar een bestand.

  2. Regel 8:

    Het pad is dat van het bestand op je schijf, gerekend vanaf de map waarin je fastapi dev startte: je projectmap. FastAPI leest het bestand en stuurt de inhoud naar de browser. De HTML staat zo in een echt .html-bestand, met kleurtjes in je editor.

Testen​

Ga naar http://127.0.0.1:8000. Je ziet de pagina uit home.html.

Gaat er iets mis?

Zie je de pagina niet? Kijk of het pad in FileResponse("...") precies klopt en of het bestand echt op die plek staat. Meer oplossingen staan op Er gaat iets mis.

Zo ziet je main.py er nu uit

Dit is je hele main.py na deze les, zonder wat je in de opdrachten maakte.

main.pydraait op de server
from fastapi import FastAPI
from fastapi.responses import FileResponse, HTMLResponse

app = FastAPI()

@app.get("/")
async def home():
return FileResponse("static/pages/home.html")

@app.get("/info")
async def info():
return {"naam": "Jouw Naam", "leeftijd": 16}

@app.get("/pagina", response_class=HTMLResponse)
async def pagina():
return """
<!DOCTYPE html>
<html>
<head>
<title>Mijn Pagina</title>
</head>
<body>
<h1>Hallo!</h1>
<p>Dit is mijn eerste HTML pagina.</p>
</body>
</html>
"""

@app.get("/styled", response_class=HTMLResponse)
async def styled():
return """
<!DOCTYPE html>
<html>
<head>
<title>Met CSS</title>
<style>
h1 { color: blue; }
p { color: gray; }
</style>
</head>
<body>
<h1>Gestylede pagina</h1>
<p>Deze tekst is grijs.</p>
</body>
</html>
"""
Controlevraag
Je server draait met de main.py van deze les. Je typt 127.0.0.1:8000/static/pages/home.html in de adresbalk. Wat krijg je?
Kies wat jij denkt. Bij het goede antwoord zie je de uitleg.

Opdrachten​

Opdracht 1: Predict - Wat gebeurt er?​

main.pydraait op de server
@app.get("/contact")
async def contact():
return FileResponse("static/pages/contact.html")
Voorspel
Wat gebeurt er op /contact als contact.html niet bestaat?
Kies wat jij denkt. Bij het goede antwoord zie je de uitleg.

Opdracht 2: Run​

Maak de mappenstructuur uit het voorbeeld (static/pages/home.html) en pas je main.py aan met FileResponse. Laadt / de pagina uit home.html? En werken /pagina en /styled nog?

Opdracht 3: Investigate - Fout pad​

Toets je voorspelling uit opdracht 1. Verander het pad in je endpoint voor / naar een bestand dat niet bestaat, bijvoorbeeld FileResponse("static/pages/oeps.html"), en herlaad. Wat zegt de browser, en welke regel in de terminal vertelt je wat er mis is?

Antwoord

De browser toont alleen Internal Server Error. In de terminal staat een lange foutmelding; scroll naar de onderste regel:

RuntimeError: File at path static/pages/oeps.html does not exist.

Dat is de regel die je iets vertelt: het bestand bestaat niet op dat pad. Een typfout in het pad geeft precies deze fout. Zet het pad daarna terug op home.html.

Opdracht 4: Make - Een tweede pagina​

Maak een tweede pagina favoriet.html over je favoriete game, film of boek, met een eigen endpoint /favoriet.

Tip

Maak het bestand in static/pages/ en een tweede functie in main.py met een eigen pad in @app.get(...).

Antwoord
static/pages/favoriet.htmlgaat zoals hij is naar de browser
<!DOCTYPE html>
<html>
<body>
<h1>Mijn favoriete game</h1>
<p>Minecraft, omdat je alles zelf kunt bouwen.</p>
</body>
</html>
main.pydraait op de server
@app.get("/favoriet")
async def favoriet():
return FileResponse("static/pages/favoriet.html")

Opdracht 5: Make - Van string naar bestand​

Zet de pagina met de <style>-tag uit HTML tonen in een bestand static/pages/styled.html, en laat het endpoint /styled dat bestand teruggeven.

Tip

Alles tussen de drie aanhalingstekens gaat naar het bestand. In Python blijft alleen de FileResponse over, en response_class=HTMLResponse is niet meer nodig.

Antwoord
static/pages/styled.htmlgaat zoals hij is naar de browser
<!DOCTYPE html>
<html>
<head>
<title>Met CSS</title>
<style>
h1 { color: blue; }
p { color: gray; }
</style>
</head>
<body>
<h1>Gestylede pagina</h1>
<p>Deze tekst is grijs.</p>
</body>
</html>

Vervang je endpoint /styled uit HTML tonen door:

main.pydraait op de server
@app.get("/styled")
async def styled():
return FileResponse("static/pages/styled.html")