Repository: pydantic/pydantic

Issue:
Discriminator field on BaseModel instances are incorrectly accessed by alias in validation
### Checks

* [x] I added a descriptive title to this issue
* [x] I have searched (google, github) for similar issues and couldn't find anything
* [x] I have read and followed [the docs](https://pydantic-docs.helpmanual.io/) and still think this is a bug

# Bug

Output of `python -c "import pydantic.utils; print(pydantic.utils.version_info())"`:
```
$ python -c "import pydantic.utils; print(pydantic.utils.version_info())"
             pydantic version: 1.9.0
            pydantic compiled: True
                 install path: ./venv/lib/python3.10/site-packages/pydantic
               python version: 3.10.2 (main, Jan 17 2022, 00:00:00) [GCC 11.2.1 20211203 (Red Hat 11.2.1-7)]
                     platform: Linux-5.16.9-200.fc35.x86_64-x86_64-with-glibc2.34
     optional deps. installed: ['typing-extensions']
```

When validating a discriminated union where the union value has been passed as a Pydantic model instance, it appears that the `_validate_discriminated_union` function is trying to access the value of the discriminator field via its alias. Since the alias does not exist on the model as an attribute, the validation fails.

I believe this is the result of a tiny mistake when setting up the `_validate_discriminated_union` function and that whenever a `BaseModel` or dataclass is detected then we should use the discriminator key and not the alias to access the discriminator value.

```py
from typing import Literal, Union

from pydantic import BaseModel, Field


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')

Top(sub=A(lit='a'))
# pydantic.error_wrappers.ValidationError: 1 validation error for Top
# sub
#   Discriminator 'literal' is missing in value (type=value_error.discriminated_union.missing_discriminator; discriminator_key=literal)

Top(sub=B(lit='b'))
# pydantic.error_wrappers.ValidationError: 1 validation error for Top
# sub
#   Discriminator 'literal' is missing in value (type=value_error.discriminated_union.missing_discriminator; discriminator_key=literal)

Top(sub=B(literal='b'))
# pydantic.error_wrappers.ValidationError: 1 validation error for Top
# sub
#   Discriminator 'literal' is missing in value (type=value_error.discriminated_union.missing_discriminator; discriminator_key=literal)
```


Discussion:

Resolving patch:
diff --git a/pydantic/fields.py b/pydantic/fields.py
--- a/pydantic/fields.py
+++ b/pydantic/fields.py
@@ -1086,7 +1086,7 @@ def _validate_discriminated_union(
         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)
 


Test patch:
diff --git a/tests/test_discrimated_union.py b/tests/test_discrimated_union.py
--- a/tests/test_discrimated_union.py
+++ b/tests/test_discrimated_union.py
@@ -267,6 +267,24 @@ class Top(BaseModel):
     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]