Cum să validezi request-urile unui API cu Pydantic și Marshmallow
In this tutorial, you'll learn about Cum să validezi request. We cover key concepts, practical examples, and best practices to help you understand and apply this topic effectively.
Validarea request-urilor asigură că datele primite de API sunt corecte, complete și sigure. În acest ghid vei învăța cum să validezi request-urile API cu Pydantic, Marshmallow și scheme personalizate.
Problema
API-ul tău primește date invalide -- câmpuri lipsă, tipuri greșite, string-uri în loc de numere. Fără validare, aceste date ajung în baza de date și cauzează erori greu de depanat.
Soluția Rapidă
1. Validare cu Pydantic (recomandat)
pip install pydantic
from pydantic import BaseModel, EmailStr, Field, validator
from typing import Optional
class UtilizatorCreate(BaseModel):
nume: str = Field(..., min_length=2, max_length=100)
email: str
varsta: int = Field(..., ge=18, le=120)
rol: Optional[str] = "user"
@validator("email")
def email_valid(cls, v):
if "@" not in v:
raise ValueError("Email invalid")
return v.lower()
@validator("nume")
def nume_fara_spatii_duble(cls, v):
return " ".join(v.split())
from fastapi import FastAPI
app = FastAPI()
@app.post("/utilizatori")
def creeaza_utilizator(u: UtilizatorCreate):
# Pydantic validează automat request body-ul
return {"mesaj": "Utilizator creat", "date": u.model_dump()}
2. Validare cu Marshmallow (Flask)
pip install marshmallow
from marshmallow import Schema, fields, validate, ValidationError
class ProdusSchema(Schema):
nume = fields.String(required=True, validate=validate.Length(min=2))
pret = fields.Float(required=True, validate=validate.Range(min=0))
stoc = fields.Integer(missing=0)
schema = ProdusSchema()
@app.route("/produse", methods=["POST"])
def creeaza_produs():
try:
date = schema.load(request.get_json())
return jsonify({"produs": date}), 201
except ValidationError as err:
return jsonify({"eroare": err.messages}), 422
3. Validare avansată cu Pydantic
from datetime import datetime
from enum import Enum
from typing import List
class StatusComanda(str, Enum):
nou = "nou"
procesat = "procesat"
trimis = "trimis"
class ArticolComanda(BaseModel):
produs_id: int
cantitate: int = Field(..., ge=1)
class ComandaCreate(BaseModel):
utilizator_id: int
articole: List[ArticolComanda] = Field(..., min_length=1)
status: StatusComanda = StatusComanda.nou
data_livrare: Optional[datetime] = None
@validator("articole")
def articole_unice(cls, v):
ids = [a.produs_id for a in v]
if len(ids) != len(set(ids)):
raise ValueError("Produse duplicate in comanda")
return v
Testare cu request invalid:
curl -X POST http://localhost:8000/utilizatori \
-H "Content-Type: application/json" \
-d '{"nume": "A", "varsta": 15}'
Output:
{
"detail": [
{"loc": ["body", "nume"], "msg": "ensure this value has at least 2 characters"},
{"loc": ["body", "email"], "msg": "field required"},
{"loc": ["body", "varsta"], "msg": "ensure this value is greater than or equal to 18"}
]
}
Prevenție
- Definește scheme de validare pentru fiecare endpoint care primește date
- Folosește type hints Python și Pydantic pentru validare automată
- Returnează cod 422 pentru erori de validare, nu 400
- Validează și pe client (frontend) dar niciodată doar pe client
Greșeli Comune
- Validare doar pe frontend -- request-urile pot veni direct prin curl, Postman sau alte servicii
- Mesaje de eroare vagi --
"eroare de validare"fără a specifica ce câmp este greșit - Ignorarea tipurilor de date -- un
inttrimis ca string"123"trebuie convertit și validat - Câmpuri opționale fără valoare implicită --
Nonepoate cauza erori în logica de business - Validare doar pe request body -- nu uita de query parameters și path parameters
Exercițiu Practic
Creează un API cu endpoint POST /comenzi care validează: ID client (int pozitiv), lista de produse (minim 1, maxim 50), adresa de livrare (string 10-200 caractere) și metoda de plată (card, ramburs, transfer).
FAQ
Built by the developers of DodaTech
Doda Browser, DodaZIP & Durga Antivirus Pro