英文:
How to set a Pydantic field value depending on other fields
问题
from pydantic import BaseModel
class Grafana(BaseModel):
user: str
password: str
host: str
port: str
api_key: str | None = None
@property
def GRAFANA_URL(self):
return f"http://{self.user}:{self.password}@{self.host}:{self.port}"
API_DATASOURCES = "/api/datasources"
API_KEYS = "/api/auth/keys"
英文:
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.
答案1
得分: 5
Option A: 使用@validator
请查看验证器文档以获取详细信息。
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'
这样,foobar
仍然是一个常规模型字段。
请注意,为了使此功能正常工作,foobar
必须在foo
和bar
之后定义。否则,您将不得不使用根验证器。
Option B: 将其作为@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
然后foobar
将不再是模型字段,因此不会包含在模式中。这可能与您相关或不相关。
Option C: 将其作为@computed_field
(仅适用于Pydantic v2!)
定义计算字段将在Pydantic 2中可用。
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'
英文:
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.
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.
Option C: Make it a @computed_field
(Pydantic v2 only!)
Defining computed fields will be available for Pydantic 2.
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'
通过集体智慧和协作来改善编程学习和解决问题的方式。致力于成为全球开发者共同参与的知识库,让每个人都能够通过互相帮助和分享经验来进步。
评论