Question: from pydantic import BaseModel class Grafana(BaseModel): user: str password: str host: str port: str api_key: str | None = None GRAFANA_URL = f"http://{user}:{password}@{host}:{port}" API_DATASOURCES = "/api/datasources" API_KEYS = "/api/auth/keys"  With Pydantic I get two unbound variables error messages for user, password, etc. in GRAFANA_URL. Is there a way to solve this? In a regular class, I would just create GRAFANA_URL in the __init__ method. With Pydantic, I'm not sure how to proceed.

Answer: Pydantic v2 In Pydantic version 2 you can define a computed field for this exact purpose. from pydantic import BaseModel, computed_field class Model(BaseModel): foo: str bar: str @computed_field @property def foobar(self) -> str: return self.foo + self.bar obj = Model(foo="a", bar="b") print(obj) # foo='a' bar='b' foobar='ab'  One nice thing about this is that foobar will be part of the the serialization schema, but not part of the validation schema. Roughly speaking, this means that the foobar field will be part of a model instance, when it is dumped/returned somewhere, but no foobar value is expected for constructing a model instance. This is very useful when for example generating OpenAPI documentations from your models. Demo, with the Model from above: ... import json schema_val = Model.model_json_schema(mode="validation") schema_ser = Model.model_json_schema(mode="serialization") print(json.dumps(schema_val, indent=4)) print(json.dumps(schema_ser, indent=4))  Output: { "properties": { "foo": { "title": "Foo", "type": "string" }, "bar": { "title": "Bar", "type": "string" } }, "required": [ "foo", "bar" ], "title": "Model", "type": "object" }  { "properties": { "foo": { "title": "Foo", "type": "string" }, "bar": { "title": "Bar", "type": "string" }, "foobar": { "readOnly": true, "title": "Foobar", "type": "string" } }, "required": [ "foo", "bar", "foobar" ], "title": "Model", "type": "object" }  See the API reference for the computed_field decorator for additional options.  Pydantic v1 Option A: Use a @validator See the validators documentation for details. from typing import Any from pydantic import BaseModel, validator class Model(BaseModel): foo: str bar: str foobar: str = "" @validator("foobar", always=True) def set_if_empty(cls, v: str, values: dict[str, Any]) -> str: if v == "": return values["foo"] + values["bar"] return v obj = Model(foo="a", bar="b") print(obj) # foo='a' bar='b' foobar='ab'  That way foobar remains a regular model field. Note that for this to work, foobar must be defined after foo and bar. Otherwise you will have to use a root validator. PS: This approach also works analogously with Pydantic v2 @field_validator and @model_validator. Option B: Make it a @property from pydantic import BaseModel class Model(BaseModel): foo: str bar: str @property def foobar(self) -> str: return self.foo + self.bar obj = Model(foo="a", bar="b") print(obj) # foo='a' bar='b' print(obj.foobar) # ab  Then foobar will not be a model field anymore and therefore not part of the schema. That may or may not be relevant to you. PS: This of course also works with Pydantic v2, though there probably is no benefit of using @property without @computed_field (see above).