diff --git a/changes/3846-chornsby.md b/changes/3846-chornsby.md new file mode 100644 index 0000000..f8daac8 --- /dev/null +++ b/changes/3846-chornsby.md @@ -0,0 +1 @@ +Fix validation of discriminated union fields with an alias when passing a model instance diff --git a/pydantic/fields.py b/pydantic/fields.py index 10b59fd..1c319cc 100644 --- a/pydantic/fields.py +++ b/pydantic/fields.py @@ -1105,7 +1105,7 @@ class ModelField(Representation): except TypeError: try: # BaseModel or dataclass - discriminator_value = getattr(v, self.discriminator_alias) + discriminator_value = getattr(v, self.discriminator_key) except (AttributeError, TypeError): return v, ErrorWrapper(MissingDiscriminator(discriminator_key=self.discriminator_key), loc) diff --git a/tests/test_discrimated_union.py b/tests/test_discrimated_union.py index a4dd501..a099fca 100644 --- a/tests/test_discrimated_union.py +++ b/tests/test_discrimated_union.py @@ -267,6 +267,24 @@ def test_discriminated_union_basemodel_instance_value(): assert isinstance(t, Top) +def test_discriminated_union_basemodel_instance_value_with_alias(): + class A(BaseModel): + literal: Literal['a'] = Field(alias='lit') + + class B(BaseModel): + literal: Literal['b'] = Field(alias='lit') + + class Config: + allow_population_by_field_name = True + + class Top(BaseModel): + sub: Union[A, B] = Field(..., discriminator='literal') + + assert Top(sub=A(lit='a')).sub.literal == 'a' + assert Top(sub=B(lit='b')).sub.literal == 'b' + assert Top(sub=B(literal='b')).sub.literal == 'b' + + def test_discriminated_union_int(): class A(BaseModel): l: Literal[1]