Fastapi - Correct way of validating fields on crud level

Viewed 23

I'm working on small fast api project (pizza delivery).

At some point I need to validate things on database level before I create new object. For instance pizza order - the pizza name comming from that order (if this pizza exists in database).

I've noticed that some people perform this kind of validation using pydantic (on schema level). I'm a bit worried it's incorrect way as schema should be just schema and shouldn't touch database at this point (Too many responsibilities).

I've come up with my own way and separated database validation on extra layer.

Validator abstract + decorator using this abstract:

class Validator(Protocol):
    """Validator abstract class"""
    def validation(db: Session):
        ...

def validator(validator: Validator):
    """Decorator for dynamic validator allocation"""
    def decorator(func):
        @wraps(func)
        def wrapper(*args, **kwargs):
            try:
                db: Session = args[0]
                schema: schemas = args[1]
            except IndexError:
                raise AttributeError("Insufficient amount of arguments for validator")
            exception = validator(schema).validation(db)
            if exception: raise exception
            return func(*args, **kwargs)
        return wrapper
    return decorator

Implementation of abstract:

class PizzaExistsValidator:
    def __init__(self, order: schemas.Order):
        self.order = order
    def validation(self, db: Session):
        if not all(get_pizza(db, ordered_pizza.pizza.name) != None
                   for ordered_pizza in self.order.pizzas):
            return PizzaExistenceException("Pizza does not exist")

Usage on db level:

@validator(PizzaExistsValidator)
def create_order(db: Session, order: schemas.Order):
    total_price = order.price
    order.pizzas = jsonable_encoder(order.pizzas)
    db_order = models.Order(**dict(order), price=total_price)
    db.add(db_order)
    db.commit()
    db.refresh(db_order)
    return db_order

I'm new in fastapi so maybe I'm not aware about any another, better way of doing the above? Appreciate any hints / feedback :)

0 Answers
Related