Invoer controleren: de inhoud controleren
max_length uit les 3 bewaakt de lengte, en een leeg veld weigert
FastAPI al, zoals je in les 4 zag. Maar een naam van drie
spaties is niet leeg en niet te lang. Maak een script spaties.py dat zo'n
naam stuurt:
import httpx
antwoord = httpx.post("http://127.0.0.1:8000/bericht", data={"naam": " ", "bericht": "hoi"})
print(antwoord.status_code, antwoord.json())
Uitvoer:
200 {'lengte': 3}
Draai lees_database.py uit les 1. Onderaan staat het nieuwe
bericht:
[ ] 3 tekens
Tussen de blokhaken staan drie spaties: in je gastenboek staat nu een bericht zonder zichtbare naam. Dat een naam uit meer dan spaties bestaat, controleer je zelf.
strip()
strip() haalt de spaties aan het begin en het eind van een tekst weg:
print(repr(" ".strip()))
print(repr(" Sara ".strip()))
Uitvoer:
''
'Sara'
repr laat de aanhalingstekens zien, zodat je de spaties ziet. Blijft er na
strip() niets over, dan bestond de naam alleen uit spaties.
De controle in het endpoint
@app.post("/bericht")
async def bericht_plaatsen(
naam: str = Form(..., max_length=30),
bericht: str = Form(..., max_length=280),
):
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}
db.commit()
return {"lengte": len(bericht)}
- Regel 6:
Een lege tekst telt in een
ifals niet waar, dusnot naam.strip()is waar als er niets overblijft. - Regel 7:
raise HTTPExceptionstopt de functie en stuurt een foutmelding, zoals de 404 in Een 404 sturen: als het item niet bestaat.
Vervang bericht_plaatsen in je main.py door deze. HTTPException komt uit
fastapi, net als Form. Zet hem daarom bij de import bovenaan:
from fastapi import FastAPI, Form, HTTPException
Draai spaties.py opnieuw.
Het is een 400 en geen 422. Een 422 komt van FastAPI zelf, als een veld niet
past bij wat er in Form staat. Een 400 stuur meestal jij, voor een regel die
je zelf bedacht. De uitzondering zag je in les 2: bij een veld
boven een megabyte stuurt Starlette zelf een 400.
Er gaat iets mis
JSONDecodeError in spaties.py
spaties.py stopt met:
json.decoder.JSONDecodeError: Expecting value: line 1 column 1 (char 0)
In de terminal van je server staat:
NameError: name 'HTTPException' is not defined
Oorzaak: HTTPException staat niet bij de import. Je server loopt vast op
de regel met raise, en stuurt een 500 met de tekst Internal Server Error.
Dat is geen JSON, dus antwoord.json() in je script kan er niets mee.
Oplossing: zet HTTPException bij de import uit fastapi, zoals hierboven.
Bij een 500 staat de echte fout altijd in de terminal van je server.
400, maar het bericht staat er toch in
De server geeft 400, maar lees_database.py laat toch een nieuwe regel met
[ ] zien.
Oorzaak: de controle staat ná het opslaan:
# FOUT
with SqliteDict("gastenboek.db") as db:
db[f"bericht_{time.time_ns()}"] = {"naam": naam, "bericht": bericht}
db.commit()
if not naam.strip():
raise HTTPException(status_code=400, detail="Vul een naam in")
# GOED
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}
db.commit()
Oplossing: controleer eerst, en sla pas op als alles klopt.
Opdrachten
Opdracht 1: Predict - Spaties eromheen
Je stuurt de naam " Sara ", met een spatie ervoor en erachter.
Vraag: geeft de server 200 of 400? En wat komt er in de database?
Antwoord
200: na strip() blijft Sara over, dus de controle laat hem door. Maar
lees_database.py laat [ Sara ] 3 tekens zien, met de spaties, want de
controle verandert naam niet. Wil je ze kwijt, zet dan naam = naam.strip()
bovenaan de functie.
Opdracht 2: Modify - Ook het bericht
Zorg dat een bericht van alleen spaties ook een 400 geeft, met de melding
Schrijf een bericht.
Tip
Dezelfde twee regels als voor de naam, met bericht in plaats van naam.
Antwoord
@app.post("/bericht")
async def bericht_plaatsen(
naam: str = Form(..., max_length=30),
bericht: str = Form(..., max_length=280),
):
if not naam.strip():
raise HTTPException(status_code=400, detail="Vul een naam in")
if not bericht.strip():
raise HTTPException(status_code=400, detail="Schrijf een bericht")
with SqliteDict("gastenboek.db") as db:
db[f"bericht_{time.time_ns()}"] = {"naam": naam, "bericht": bericht}
db.commit()
return {"lengte": len(bericht)}
Een bericht van drie spaties geeft nu 400 {'detail': 'Schrijf een bericht'}.
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),
):
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}
db.commit()
return {"lengte": len(bericht)}
De lengte bewaakt FastAPI, de inhoud jij.
Door naar les 6: getallen met een grens.