diff --git a/changes/1732-PrettyWood.md b/changes/1732-PrettyWood.md new file mode 100644 index 0000000000..6f0a79f3aa --- /dev/null +++ b/changes/1732-PrettyWood.md @@ -0,0 +1 @@ +support `default_factory` with `BaseModel.construct` \ No newline at end of file diff --git a/pydantic/main.py b/pydantic/main.py index c872f1e3b5..4e543f4f86 100644 --- a/pydantic/main.py +++ b/pydantic/main.py @@ -527,7 +527,10 @@ def construct(cls: Type['Model'], _fields_set: Optional['SetStr'] = None, **valu Default values are respected, but no other validation is performed. """ m = cls.__new__(cls) - object.__setattr__(m, '__dict__', {**deepcopy(cls.__field_defaults__), **values}) + # default field values + fields_values = {name: field.get_default() for name, field in cls.__fields__.items() if not field.required} + fields_values.update(values) + object.__setattr__(m, '__dict__', fields_values) if _fields_set is None: _fields_set = set(values.keys()) object.__setattr__(m, '__fields_set__', _fields_set) diff --git a/tests/test_construction.py b/tests/test_construction.py index c60b7f7199..93abb6e032 100644 --- a/tests/test_construction.py +++ b/tests/test_construction.py @@ -3,7 +3,7 @@ import pytest -from pydantic import BaseModel +from pydantic import BaseModel, Field class Model(BaseModel): @@ -275,3 +275,13 @@ class X(BaseModel): # deep['deep_thing'] gets modified assert x.deep['deep_thing'] == [1, 2, 3] assert y.deep['deep_thing'] == [1, 2, 3] + + +def test_construct_default_factory(): + class Model(BaseModel): + foo: List[int] = Field(default_factory=list) + bar: str = 'Baz' + + m = Model.construct() + assert m.foo == [] + assert m.bar == 'Baz'