fix: keep order of fields with BaseModel.construct() (#2282)

* fix: keep order of fields with `BaseModel.construct()`

closes #2281

* chore: keep extra fields in construct

thanks @layday!
This commit is contained in:
Eric Jolibois
2021-02-13 12:26:43 +01:00
committed by GitHub
parent 9ca8fe85eb
commit ad7862f032
3 changed files with 30 additions and 2 deletions
+1
View File
@@ -0,0 +1 @@
fix: keep order of fields with `BaseModel.construct()`
+7 -2
View File
@@ -611,10 +611,15 @@ class BaseModel(Representation, metaclass=ModelMetaclass):
"""
Creates a new model setting __dict__ and __fields_set__ from trusted or pre-validated data.
Default values are respected, but no other validation is performed.
Behaves as if `Config.extra = 'allow'` was set since it adds all passed values
"""
m = cls.__new__(cls)
# default field values
fields_values = {name: field.get_default() for name, field in cls.__fields__.items() if not field.required}
fields_values: Dict[str, Any] = {}
for name, field in cls.__fields__.items():
if name in values:
fields_values[name] = values[name]
elif not field.required:
fields_values[name] = field.get_default()
fields_values.update(values)
object_setattr(m, '__dict__', fields_values)
if _fields_set is None:
+22
View File
@@ -35,6 +35,28 @@ def test_construct_fields_set():
assert m.dict() == {'a': 3, 'b': -1}
def test_construct_allow_extra():
"""construct() should allow extra fields"""
class Foo(BaseModel):
x: int
assert Foo.construct(x=1, y=2).dict() == {'x': 1, 'y': 2}
def test_construct_keep_order():
class Foo(BaseModel):
a: int
b: int = 42
c: float
instance = Foo(a=1, b=321, c=3.14)
instance_construct = Foo.construct(**instance.dict())
assert instance == instance_construct
assert instance.dict() == instance_construct.dict()
assert instance.json() == instance_construct.json()
def test_large_any_str():
class Model(BaseModel):
a: bytes