Business
Jobs
  • About Us
  • Solutions
    • Job Postings
      Post your job and receive qualified candidates in 48h.
    • Candidate Assessments
      500+ technical and psychological tests, plus anti-fraud.
    • Headhunting
      Tailor-made executive search from start to finish.
    • Payroll + EOR
      Payroll dispersal and EOR across 15+ LATAM countries.
  • Pricing
  • Jobs

0

665
Views
¿Cómo usar tipos de unión discriminados en la validación del cuerpo FastAPI? (Unión de modelos)

Conozco un concepto de Typescript llamado Uniones discriminadas . Eso es algo en lo que pones 2 estructuras (clases, etc.) y el tipo se decide según los valores de una estructura. Estoy tratando de lograr algo similar en FastAPI con validación Pydantic . Hay dos cargas de solicitud diferentes que puedo recibir. Si es uno u otro depende de la variable accountType . Si es una creative , debe ser validada por RegistrationPayloadCreative y si es una brand , debe ser validada por RegistrationPayloadBrand . ¿Cómo logro esto? No pude encontrar ninguna otra solución.

El problema es que o vuelve

unexpected value; permitted: 'creative' (type=value_error.const; given=brand; permitted=('creative',))

O no funciona en absoluto.

 class RegistrationPayloadBase(BaseModel): first_name: str last_name: str email: str password: str class RegistrationPayloadCreative(RegistrationPayloadBase): accountType: Literal['creative'] class RegistrationPayloadBrand(RegistrationPayloadBase): company: str phone: str vat: str accountType: Literal['brand'] class A(BaseModel): b: Union[RegistrationPayloadBrand, RegistrationPayloadCreative] def main(): A(b={'first_name': 'sdf', 'last_name': 'sdf', 'email': 'sdf', 'password': 'sdfds', 'accountType': 'brand'}) if __name__ == '__main__': main()
over 4 years ago · Santiago Trujillo
2 answers
Answer question

0

Debería usar __root__ y parse_obj en su lugar.

 from typing import Union from pydantic import BaseModel class PlanetItem(BaseModel): id: str planet_name: str # ... class CarItem(BaseModel): id: str name: str # ... class EitherItem(BaseModel): __root__: Union[PlanetItem, CarItem] @app.get("/items/{item_id}", response_model=EitherItem) def get_items(item_id): return EitherItem.parse_obj(response) # Now you get either PlanetItem or CarItem

Crédito: https://github.com/tiangolo/fastapi/issues/2279#issuecomment-787517707

over 4 years ago · Santiago Trujillo Report

0

El mensaje de error es un poco engañoso ya que el problema es que los campos de empresa/teléfono/IVA son obligatorios en RegistrationPayloadBrand.

Asi que:

 >>> A(b={'first_name': 'sdf', 'last_name': 'sdf', 'email': 'sdf', 'password': 'sdfds', 'accountType': 'brand', 'company':'foo','vat':'bar', 'phone':'baz'}) A(b=RegistrationPayloadBrand(first_name='sdf', last_name='sdf', email='sdf', password='sdfds', company='foo', phone='baz', vat='bar', accountType='brand')) >>> A(b={'first_name': 'sdf', 'last_name': 'sdf', 'email': 'sdf', 'password': 'sdfds', 'accountType': 'creative'}) A(b=RegistrationPayloadCreative(first_name='sdf', last_name='sdf', email='sdf', password='sdfds', accountType='creative'))

O haciéndolos opcionales (si la carga útil no necesariamente contiene esos campos)

 class RegistrationPayloadBrand(RegistrationPayloadBase): company: Optional[str] phone: Optional[str] vat: Optional[str] accountType: Literal['brand'] >>> A(b={'first_name': 'sdf', 'last_name': 'sdf', 'email': 'sdf', 'password': 'sdfds', 'accountType': 'brand'}) A(b=RegistrationPayloadBrand(first_name='sdf', last_name='sdf', email='sdf', password='sdfds', company=None, phone=None, vat=None, accountType='brand')) >>> A(b={'first_name': 'sdf', 'last_name': 'sdf', 'email': 'sdf', 'password': 'sdfds', 'accountType': 'creative'}) A(b=RegistrationPayloadCreative(first_name='sdf', last_name='sdf', email='sdf', password='sdfds', accountType='creative'))

resolverá el problema

over 4 years ago · Santiago Trujillo Report
Answer question
Find remote jobs

Discover the new way to find a job!

Top jobs
Top job categories
Business
Post vacancy Pricing Sales
Legal
Terms and conditions Privacy policy
© 2026 PeakU Inc. All Rights Reserved.
Andres GPT
Show me some job opportunities
There's an error!