request_query.py 1.7 KB

1234567891011121314151617181920212223242526272829303132333435363738394041424344454647484950515253
  1. # (c) Nelen & Schuurmans
  2. from typing import List
  3. from fastapi import Query
  4. from pydantic import field_validator
  5. from clean_python import Filter
  6. from clean_python import PageOptions
  7. from clean_python import ValueObject
  8. __all__ = ["RequestQuery"]
  9. class RequestQuery(ValueObject):
  10. limit: int = Query(50, ge=1, le=100, description="Page size limit")
  11. offset: int = Query(0, ge=0, description="Page offset")
  12. order_by: str = Query(
  13. default="id", enum=["id", "-id"], description="Field to order by"
  14. )
  15. @field_validator("order_by")
  16. def validate_order_by_enum(cls, v, _):
  17. # the 'enum' parameter doesn't actually do anthing in validation
  18. # See: https://github.com/tiangolo/fastapi/issues/2910
  19. allowed = cls.model_json_schema()["properties"]["order_by"]["enum"]
  20. if v not in allowed:
  21. raise ValueError(f"'order_by' must be one of {allowed}")
  22. return v
  23. def as_page_options(self) -> PageOptions:
  24. if self.order_by.startswith("-"):
  25. order_by = self.order_by[1:]
  26. ascending = False
  27. else:
  28. order_by = self.order_by
  29. ascending = True
  30. return PageOptions(
  31. limit=self.limit, offset=self.offset, order_by=order_by, ascending=ascending
  32. )
  33. def filters(self) -> List[Filter]:
  34. result = []
  35. for name in self.model_fields:
  36. if name in {"limit", "offset", "order_by"}:
  37. continue
  38. # deal with list query paramerers
  39. value = getattr(self, name)
  40. if value is not None:
  41. if not isinstance(value, list):
  42. value = [value]
  43. result.append(Filter(field=name, values=value))
  44. return result