Dynamically adding fields inplace to an existing model classes?

See original GitHub issue

Hi, is there a way to dynamically add a field to a model class?

I’m creating some models using Dynamic Model Creation. As I’m using a pluggable architecture, I would like to add further fields to these model classes after their creation (but before instances have been created)?

Is this possible? I’m looking for something like model.add_fields(foo=(str, ...), bar=123), i.e. a class method with similar arguments the **field_definitions arguments of create_model().

It needs to be “in-place”, i.e., not creating a new model class, as the model class is already embedded in other model classes.

Thank you and best regards, Martin

Output of python -c "import pydantic.utils; print(pydantic.utils.version_info())":

             pydantic version: 1.6.1
            pydantic compiled: True
                 install path: C:\Program Files\Python38\Lib\site-packages\pydantic
               python version: 3.8.1 (tags/v3.8.1:1b293b6, Dec 18 2019, 23:11:46) [MSC v.1916 64 bit (AMD64)]
                     platform: Windows-10-10.0.18362
     optional deps. installed: ['typing-extensions', 'email-validator']

Issue Analytics

  • State:closed
  • Created 3 years ago
  • Reactions:5
  • Comments:7 (3 by maintainers)

github_iconTop GitHub Comments

13reactions
PrettyWoodcommented, Sep 19, 2020

Ah sorry I didn’t see the inplace mention, which is why you’re playing with __fields__ I reckon. If so I would probably use ModelField.infer like this:

from typing import Any, Dict, Optional

from pydantic import BaseModel
from pydantic.fields import ModelField


class Model(BaseModel):
    foo: str

    @classmethod
    def add_fields(cls, **field_definitions: Any):
        new_fields: Dict[str, ModelField] = {}
        new_annotations: Dict[str, Optional[type]] = {}

        for f_name, f_def in field_definitions.items():
            if isinstance(f_def, tuple):
                try:
                    f_annotation, f_value = f_def
                except ValueError as e:
                    raise Exception(
                        'field definitions should either be a tuple of (<type>, <default>) or just a '
                        'default value, unfortunately this means tuples as '
                        'default values are not allowed'
                    ) from e
            else:
                f_annotation, f_value = None, f_def

            if f_annotation:
                new_annotations[f_name] = f_annotation

            new_fields[f_name] = ModelField.infer(name=f_name, value=f_value, annotation=f_annotation, class_validators=None, config=cls.__config__)

        cls.__fields__.update(new_fields)
        cls.__annotations__.update(new_annotations)


m = Model(foo='qwe')

Model.add_fields(bar=(str, ...), baz='qwe')

m = Model(foo='qwe')

# pydantic.error_wrappers.ValidationError: 1 validation error for Model
# bar
#   field required (type=value_error.missing)

Note that I copied the part about annotations but it’s not really complete and can be removed. Hope it helps!

7reactions
PrettyWoodcommented, Sep 19, 2020

Hello @mcgfeller! I think you already answered your own question 😉 I would go with something like this

from pydantic import BaseModel as PydanticBaseModel, create_model

class BaseModel(PydanticBaseModel):
    @classmethod
    def with_fields(cls, **field_definitions):
        return create_model('ModelWithFields', __base__=cls, **field_definitions)

With a model like

class Model(BaseModel):
    foo: str
    bar: int = 123

you could simply create a new one

NewModel = Model.with_fields(baz=(int, ...))
NewModel(foo='awe')

pydantic.error_wrappers.ValidationError: 1 validation error for ModelWithFields
baz
  field required (type=value_error.missing)
Read more comments on GitHub >

github_iconTop Results From Across the Web

Dynamically adding fields inplace to an existing model classes?
Hi, is there a way to dynamically add a field to a model class? I'm creating some models using Dynamic Model Creation.
Read more >
dynamically add field to a form - python - Stack Overflow
I have a submit button and a button to "Add additional Field". I understand I can add fields using __init__ method in the...
Read more >
ModelForm: Dynamically change model and fields
dynamically change model and fields for ModelForm class. I have tried following: class Form(ModelForm): class Meta: model = None fields = ('',)
Read more >
How to add and remove input fields dynamically using jQuery ...
Use the append() method to add the input field code to the existing HTML document. $('#newinput').append(newRowAdd);. Use the remove() method to ...
Read more >
Add Remove Input Fields Dynamically using jQuery
The dynamic input fields feature can be easily integrated using jQuery. You can add multiple fields and remove fields easily.
Read more >

github_iconTop Related Medium Post

No results found

github_iconTop Related StackOverflow Question

No results found

github_iconTroubleshoot Live Code

Lightrun enables developers to add logs, metrics and snapshots to live code - no restarts or redeploys required.
Start Free

github_iconTop Related Reddit Thread

No results found

github_iconTop Related Hackernoon Post

No results found

github_iconTop Related Tweet

No results found

github_iconTop Related Dev.to Post

No results found

github_iconTop Related Hashnode Post

No results found