Invoer controleren: getallen met een grens
Een gastenboek met een cijfer voor de site, van 1 tot en met 10. In de HTML staat dat netjes:
<input type="number" name="cijfer" placeholder="cijfer" min="1" max="10" required>
Maar min en max zijn net als maxlength uit les 2: de
browser houdt je tegen, een script niet. Op de server kan een cijfer dan
honderd zijn, of 11, of 0.
Een getal met een grens
@app.post("/bericht")
async def bericht_plaatsen(
naam: str = Form(..., max_length=30),
bericht: str = Form(..., max_length=280),
cijfer: int = Form(..., ge=1, le=10),
):
if not naam.strip():
raise HTTPException(status_code=400, detail="Vul een naam in")
with SqliteDict("gastenboek.db") as db:
db[f"bericht_{time.time_ns()}"] = {"naam": naam, "bericht": bericht, "cijfer": cijfer}
db.commit()
return {"lengte": len(bericht), "cijfer": cijfer}
- Regel 5:
intzegt: dit moet een geheel getal zijn.ge=1betekent groter dan of gelijk aan 1,le=10kleiner dan of gelijk aan 10. - Regel 10:
Het cijfer gaat mee de database in.
Vervang bericht_plaatsen door deze. Zette je in opdracht 2 van
les 5 ook een controle op het bericht, neem die twee regels dan
mee, onder de controle op de naam. In de code van deze les staan ze niet, net
als in de stand van les 5.
Zet het <input> met name="cijfer" in static/formulier.html, binnen het
<form>, zodat ook het formulier een cijfer meestuurt.
Doe de test
Een script cijfer.py probeert vier cijfers:
import httpx
adres = "http://127.0.0.1:8000/bericht"
for cijfer in ["8", "honderd", "11", "0"]:
antwoord = httpx.post(adres, data={"naam": "Sara", "bericht": "hoi", "cijfer": cijfer})
if antwoord.status_code == 200:
print(cijfer, "->", antwoord.json())
else:
print(cijfer, "->", antwoord.status_code, antwoord.json()["detail"][0]["msg"])
Een formulier stuurt alles als tekst, ook "8". FastAPI maakt er een getal van,
en weigert wat geen getal is of buiten de grens valt. In je functie is cijfer
dus altijd een getal van 1 tot en met 10.
Er gaat iets mis
Elk verzoek geeft 422 met cijfer en Field required, ook vanuit het
formulier.
Oorzaak: het veld komt niet mee. In het formulier heet het veld anders dan
de parameter, of het <input> staat buiten het <form>. Een script uit een
eerdere les, zoals fouten.py, stuurt het helemaal niet mee.
Oplossing: controleer dat er name="cijfer" staat, binnen het <form>.
Zet in een script "cijfer": "8" bij de data.
Opdrachten
Opdracht 1: Predict - Een half cijfer
Je stuurt als cijfer 7.5.
Vraag: wat antwoordt de server?
Antwoord
422, met Input should be a valid integer, unable to parse string as an integer. Een int is een geheel getal; 7.5 is dat niet.
Zo ziet je main.py er nu uit
import time
from fastapi import FastAPI, Form, HTTPException
from fastapi.staticfiles import StaticFiles
from sqlitedict import SqliteDict
app = FastAPI()
app.mount("/static", StaticFiles(directory="static"), name="static")
@app.post("/bericht")
async def bericht_plaatsen(
naam: str = Form(..., max_length=30),
bericht: str = Form(..., max_length=280),
cijfer: int = Form(..., ge=1, le=10),
):
if not naam.strip():
raise HTTPException(status_code=400, detail="Vul een naam in")
with SqliteDict("gastenboek.db") as db:
db[f"bericht_{time.time_ns()}"] = {"naam": naam, "bericht": bericht, "cijfer": cijfer}
db.commit()
return {"lengte": len(bericht), "cijfer": cijfer}
De lengte en het cijfer bewaakt FastAPI, de naam jij.
Door naar les 7: een keuze uit een lijst.