Question: I'm using the pydantic `BaseModel` with a validator like this:

```
from datetime import date
from typing import List, Optional
from pydantic import BaseModel, BaseConfig, validator

class Model(BaseModel):
    class Config(BaseConfig):
        allow_population_by_alias = True
        fields = {
            "some_date": {
                "alias": "some_list"
            }
        }
    some_date: Optional[date]
    some_list: List[date]

    @validator("some_date", pre=True, always=True)
    def validate_date(cls, value):
        if len(value) < 2: # here value is some_list
            return None
        return value[0] # return the first value - let's assume it's a date string

# This reproduces the problem
m = Model(some_list=['2019-01-03'])

```

I would like to compute the value of `some_date` based on the value of `some_list` and make it `None` if a certain condition met. 

My JSON never contains the field `some_date`, it's always populated based on `some_list` hence `pre=True, always=True`. However the default validator for `some_date` will run *after* my custom one, which will fail if `validate_date` returns `None`.

Is there a way to create such a field which is only computed by another one and still can be `Optional`?

Answer: 
If you want to be able to dynamically modify a field according to another one, you can use the `values` argument. It holds all the previous fields, and careful: the **order matters**. You could do this either using a `validator` or a `root_validator`.

With a `validator`
------------------

```py
>>> from datetime import date
>>> from typing import List, Optional
>>> from pydantic import BaseModel, validator
>>> class Model(BaseModel):
        some_list: List[date]
        some_date: Optional[date]

        @validator("some_date", always=True)
        def validate_date(cls, value, values):
            if len(values["some_list"]) < 2:
                return None
            return values["some_list"][0]

>>> Model(some_list=['2019-01-03', '2020-01-03', '2021-01-03'])
Model(some_list=[datetime.date(2019, 1, 3), datetime.date(2020, 1, 3), datetime.date(2021, 1, 3)],
      some_date=datetime.date(2019, 1, 3))

```

But as I said if you exchange the order of `some_list` and `some_date`, you will have a `KeyError: 'some_list'`!

With a `root_validator`
-----------------------

Another option would be to use a `root_validator`. These act on all fields:

```py
>>> class Model(BaseModel):
        some_list: List[date]
        some_date: Optional[date]

        @root_validator
        def validate_date(cls, values):
            if not len(values["some_list"]) < 2:
                values["some_date"] = values["some_list"][0]
            return values

>>> Model(some_list=['2019-01-03', '2020-01-03', '2021-01-03'])
Model(some_list=[datetime.date(2019, 1, 3), datetime.date(2020, 1, 3), datetime.date(2021, 1, 3)],
      some_date=datetime.date(2019, 1, 3))

```
You should be able to use `values` according to [pydantic docs](https://pydantic-docs.helpmanual.io/usage/validators/)

> 
> you can also add any subset of the following arguments to the
>  signature (the names must match): 
> 
> 
> values: a dict containing the
>  name-to-value mapping of any previously-validated fields 
> 
> 
> config: the
>  model config 
> 
> 
> field: the field being validated
> 
> 
> \*\*kwargs: if provided, this will include the arguments above not explicitly listed in the signature
> 
> 
> 

```py
@validator()
def set_value_to_zero(cls, v, values):
    # look up other value in values, set v accordingly.

```