Pydantic Ignore, Allow or Deny (with Error) Extra Input Fields Not Defined in Model Schema

If you are using Pydantic in Python, which is an excellent data parsing and validation library, you’ll often want to do one of the following three things with extra fields or attributes that are passed in the input data to build the models:

  • Ignore the extra fields or attributes, i.e., they should not be present in the output model. This is the default behaviour.
  • Allow the extra fields or attributes passed in the input data to be present in the output model.
  • Deny the extra fields or attributes by throwing an exception.

Given the first one is the default, in some cases you may want to opt in for the second or third option. Let’s see how to do that with a Post model example.

from pydantic import BaseModel, ValidationError

class Post(BaseModel):
    id: int
    title: str
    body: str

try:
    data = {
        'id': 1,
        'title': 'First Post',
        'body': 'Post body',
        'extra': 'Extra field', # Will be ignored
    }
    post = Post(**data)
    print(post)
except ValidationError as e:
    print(e)

In the code above, we create a simple Post model with id, title and body attributes or fields. We then create a model out of it with sample input data that contains a random extra field.

By default the extra field will be ignored (first option above) and this is what the post model will look like:

print(post)
id=1 title='First Post' body='Post body'

Ok, so what if we want to allow passing of incoming extra fields in the input? We will have to specify that in the extra option via Model Config like this:

from pydantic import BaseModel, ValidationError, Extra

class PostModel(BaseModel):
    id: int
    title: str
    body: str

    class Config:
        extra = Extra.allow # or 'allow' str

We specify a Config class inside the model with extra = Extra.allow or extra = 'allow'. This is what the new post model will look like now:

print(post)
id=1 title='First Post' body='Post body' extra='Extra field'

The extra field is now a part of post.

Another common scenario is to completely deny any extra fields, i.e., raise an error (third option from the list above) for additional attributes. To achieve that, we will have to pass Extra.forbid or 'forbid' to the extra config option.

from pydantic import ...

class PostModel(BaseModel):
    ...

    class Config:
        extra = Extra.forbid

try:
    data = {
        ...
        'extra': 'Extra field',
    }
    ...
except ValidationError as e:
    print(e)

Now when the code runs, it’ll raise a ValidationError exception. This is what you’ll get from print(e):

1 validation error for PostModel
extra
  extra fields not permitted (type=value_error.extra)

Bonus: There’s a shorter way to specify the extra config option if that is the only option you’re configuring.

class PostModel(BaseModel, extra=Extra.forbid):
    ...

Although I still prefer the Config inner class approach most of the time, since I configure multiple config options and specifying a list of them inside a class is much more cleaner/maintainable.

Leave a Reply

Your email address will not be published.