Pydantic: [Question]Is 'allOf' supported by Pydantic?

Created on 16 Apr 2019  ยท  6Comments  ยท  Source: samuelcolvin/pydantic


Question

For bugs/questions:

  • OS: CentOS 7.5
  • Python version: 3.6.0
  • Pydantic version: 0.19

Does pydantic currently support polymorphism/inheritance usingallOf? For example if I have the following code (taken from https://github.com/OAI/OpenAPI-Specification/blob/master/versions/3.0.0.md#models-with-composition):

from pydantic import BaseModel, Schema

def Error(BaseModel):
    message: str = Schema(..., description="")
    code: int = Schema(..., description="")

def ExtendedErrorModel(Error):
    rootCause: str= Schema(..., description="")

If I were to generate the schema for ExtendedErrorModel I should get something that matches the following which uses allOf to signify that if I'm creating an ExtendedErrorModel object, it not only specifies rootCause but also code and message :

components:
  schemas:
    ErrorModel:
      type: object
      required:
      - message
      - code
      properties:
        message:
          type: string
        code:
          type: integer
          minimum: 100
          maximum: 600
    ExtendedErrorModel:
      allOf:
      - $ref: '#/components/schemas/ErrorModel'
      - type: object
        required:
        - rootCause
        properties:
          rootCause:
            type: string

However when it's actually generated, everything is flattened so the properties from the ErrorModel appear regularly on the ExtendedErrorModel. Which is how it should validate it, but not how the OpenAPI schema should appear:

components:
  schemas:
    ErrorModel:
      type: object
      required:
      - message
      - code
      - rootCause
      properties:
        message:
          type: string
        code:
          type: integer
          minimum: 100
          maximum: 600
        rootCause:
          type: string
question

Most helpful comment

Lol yeah sure, I can take a look into a potential solution when I have some free time this weekend to see if it would work.

Thank you!

All 6 comments

Question for @tiangolo. He's the expert on schema.

Thanks for tagging me @samuelcolvin .

@bquestions, so, generating schemas with inheritance using allOf as you suggest, is currently not supported. Inheritance of Pydantic models is supported and works, but the generated JSON Schema is flattened as you have noticed.

I think implementing it would be non-trivial, and I'm not sure if there would be any advantage of having it.

For example, FastAPI is based on Pydantic, built around OpenAPI, it generates OpenAPI schemas automatically, etc. And using the current implementation of Pydantic models has worked for most of the use cases (all the ones I know).

On the other side, if it was implemented that way, I'm not sure it would be the best option. For example, let's say a client gets to see a User model on the OpenAPI schema, and this model inherited from UserInDB, and that model, in turn, inherited from UserBase. In this case, the client would have to deal with 3 models/schemas, in a chain of inheritance. While he actually just cared about the User model, the other models are never even used by him but by the backend directly. And still he would have to deal with multiple inheritance, etc.

Thank you for the response @tiangolo. The problem is that in the project I'm working on, we have base schema definitions from one library that are being extended in another library so being able to ref in an allOf would be helpful if one wanted to see the parent schema for the object vs creating a new object. In your example, instead of seeing the chain from User --> UserInDB --> UserBase you'd have this brand new schema/model called User vs that the User builds from other schemas (similar to the example in the OpenAPI docs).

If I'm understanding OpenAPI schemas correctly, wouldn't seeing that progression be useful since we are extending models vs duplicating schema properties on similar models vs just using the allOf property? In terms of functionality I want to write the pydantic schemas how they currently are (ie in my example), I just want the schemas to display using allOf if that's possible

Hmm, I see @bquestions , it's currently not possible :disappointed:.

I think the implementation would be non-trivial, it would probably require fiddling with the Python metaclass to inspect the inheritance chain, etc. And I guess it would have to be optional, to support the default case. But maybe you or someone else wants to take a stab at it and start a PR :grin: .

Lol yeah sure, I can take a look into a potential solution when I have some free time this weekend to see if it would work.

Thank you!

@bquestions You might be able to implement a custom validator and use schema_extra (recently added) to override the JSON Schema. It might work for your use case.


On the other side, it seems allOf might not be necessarily appropriate for inheritance:

allOf can not be used to โ€œextendโ€ a schema to add more details to it in the sense of object-oriented inheritance.

That's because in JSON schema, what would be a "subclass" (in allOf) wouldn't be able to override something already declared in other class. So, a subclass couldn't declare an attribute as optional if the parent class already declared it as required. Even though you can do it in OO inheritance and in Pydantic.

I think we can close this issue as it's specifically related to allOf in the context of inheritance.

If later we talk about allOf in another context, it would be better in a new issue, to avoid confusion.

Was this page helpful?
0 / 5 - 0 ratings

Related issues

dmfigol picture dmfigol  ยท  38Comments

jasonkuhrt picture jasonkuhrt  ยท  21Comments

DrPyser picture DrPyser  ยท  19Comments

Yolley picture Yolley  ยท  18Comments

demospace picture demospace  ยท  26Comments