Home > Software engineering >  Accessing parent attributes in Pydantic Classes in order to perform validation
Accessing parent attributes in Pydantic Classes in order to perform validation

Time:07-20

The following classes are implemented using pydantic.

class Catalog(BaseModel):
    id: constr(min_length=1)
    description: constr(min_length=1)
    title: Optional[str]
    type: constr(min_length=1) = Field("Catalog", const=True)

class Collection(Catalog):
    title: Optional[str]
    keywords: Optional[List[str]]
    type: constr(min_length=1) = Field("Collection", const=True)

How can I extend/inherit the Collection class and perform validation on its attributes?

More practically do the following:

class ExtendedCollection(Collection):
    field1: Optional[str]

    @validator('type')
    def type_must_match_collection(cls, v):
        if 'Collection' != v:
            raise TypeError('This is not a Collection!')
        return v

I have the following json

tst_col = {
    "type": "Collection",
    "id": "123",
    "title": "A title",
    "description": "A description",
    "version": "V2021",
    "keywords": [
        "Europe",
        "GISCO"
    ]
}


A. If I try to initialize the class like this (which I think is the way to go)

ExtendedCollection(Collection=tst_col)

then I get the following errors:


....

pydantic.error_wrappers.ValidationError: 6 validation errors for ExtendedCollection

id
  field required (type=value_error.missing)
description
  field required (type=value_error.missing)
license
  field required (type=value_error.missing)
field1
  field required (type=value_error.missing)

B. On the other hand, if I try to initialize the class like this

ExtendedCollection(Collection=Collection(tst_col))

then I get the following error:

__init__() takes exactly 1 positional argument (2 given)

CodePudding user response:

As the error said you try to create an ExtendedCollection object but you don't give id,description, license, field1

If you want to create a object with thoses variables already set by default use a default value:

class Foo(BaseModel):
    count: int
    size: float = None

or use optional like you did:


class Collection(Catalog):
    title: Optional[str] = None
    keywords: Optional[str] = None

If you don't use one of theses solutions you need to provide the variables in your input json

After question update:

from typing import Optional, List

from pydantic import BaseModel, validator, constr, Field


class Catalog(BaseModel):
    id: constr(min_length=1)
    description: constr(min_length=1)
    title: Optional[str]
    type: constr(min_length=1) = Field("Catalog", const=True)


class Collection(Catalog):
    title: Optional[str]
    keywords: Optional[List[str]]
    type: constr(min_length=1) = Field("Collection", const=True)


class ExtendedCollection(Collection):
    field1: Optional[str]

    @validator('type')
    def type_must_match_collection(cls, v):
        if 'Collection' != v:
            raise TypeError('This is not a Collection!')
        return v


tst_col = {
    "type": "Collection",
    "id": "123",
    "title": "A title",
    "description": "A description",
    "version": "V2021",
    "keywords": [
        "Europe",
        "GISCO"
    ]
}

data: ExtendedCollection = ExtendedCollection(**tst_col)
print(data.json())

result

{
  "id": "123", 
  "description": "A description", 
  "title": "A title", 
  "type": "Collection", 
  "keywords": ["Europe", "GISCO"], 
  "field1": null
}
  • Related