在 Pydantic 的 Basemodel 中包含特殊字符
Including special character in Basemodel for Pydantic
我正在尝试使用包含“$”符号的键创建一个 Pydantic 基础模型。它看起来像这样:
class someModel(BaseModel):
$something:Optional[str] = None
然后我得到SyntaxError: invalid syntax
。
但是我需要保留键名 $something
以便在其他部分使用。在这种情况下有没有办法允许美元符号?
您可以使用 Field(alias=...)
来使用不同的(有效的)变量名。
from pydantic import BaseModel, Field
class SomeModel(BaseModel):
something: Optional[str] = Field(alias="$something", default=None)
我还添加了一个默认值 None
,因为您的代码中有它。
这是一个工作示例(编辑:已更新以显示如何获取变量名称的别名,如果您以后需要使用它):
import logging
from typing import Optional
from fastapi import FastAPI, Request
from pydantic import BaseModel, Field
logging.basicConfig(level=logging.INFO, format="%(levelname)-9s %(asctime)s - %(name)s - %(message)s")
LOGGER = logging.getLogger(__name__)
app = FastAPI()
class SomeModel(BaseModel):
something: Optional[str] = Field(alias="$something", default=None)
@app.post("/")
async def root(request: Request, parsed_body: SomeModel):
# A dict of all the model fields and their properties
LOGGER.info(f"SomeModel.__fields__: {SomeModel.__fields__}")
# To get the alias of the variable name
something_alias = SomeModel.__fields__["something"].alias
LOGGER.info(f"something_alias: {something_alias}")
# Edit: prefer to use "parsed_body_by_alias" than raw_body. Leaving here to show the difference.
raw_body: bytes = await request.body()
LOGGER.info(f"raw_body: {raw_body}")
# Edit: This is better as you get validated / parsed values, including defaults if applicable.
parsed_body_by_alias = parsed_body.dict(by_alias=True)
LOGGER.info(f"parsed_body_by_alias: {parsed_body_by_alias}")
# If you just want "something" instead of "$something"
LOGGER.info(f"parsed_body: {parsed_body}")
LOGGER.info(f"parsed_body.something: {parsed_body.something}")
return 1
if __name__ == "__main__":
import uvicorn
uvicorn.run(app, host="127.0.0.1", port=8080)
如果您 运行 代码然后发送 POST 正文:
{"$something": "bar"}
您会看到如下内容:
INFO xxx - __main__ - SomeModel.__fields__: {'something': ModelField(name='something', type=Optional[str], required=False, default=None, alias='$something')}
INFO xxx - __main__ - something_alias: $something
INFO xxx - __main__ - raw_body: b'{"$something": "bar"}'
INFO xxx - __main__ - parsed_body_by_alias: {'$something': 'bar'}
INFO xxx - __main__ - parsed_body: something='bar'
INFO xxx - __main__ - parsed_body.something: bar
INFO: 127.0.0.1:xxxxx - "POST / HTTP/1.1" 200 OK
我正在尝试使用包含“$”符号的键创建一个 Pydantic 基础模型。它看起来像这样:
class someModel(BaseModel):
$something:Optional[str] = None
然后我得到SyntaxError: invalid syntax
。
但是我需要保留键名 $something
以便在其他部分使用。在这种情况下有没有办法允许美元符号?
您可以使用 Field(alias=...)
来使用不同的(有效的)变量名。
from pydantic import BaseModel, Field
class SomeModel(BaseModel):
something: Optional[str] = Field(alias="$something", default=None)
我还添加了一个默认值 None
,因为您的代码中有它。
这是一个工作示例(编辑:已更新以显示如何获取变量名称的别名,如果您以后需要使用它):
import logging
from typing import Optional
from fastapi import FastAPI, Request
from pydantic import BaseModel, Field
logging.basicConfig(level=logging.INFO, format="%(levelname)-9s %(asctime)s - %(name)s - %(message)s")
LOGGER = logging.getLogger(__name__)
app = FastAPI()
class SomeModel(BaseModel):
something: Optional[str] = Field(alias="$something", default=None)
@app.post("/")
async def root(request: Request, parsed_body: SomeModel):
# A dict of all the model fields and their properties
LOGGER.info(f"SomeModel.__fields__: {SomeModel.__fields__}")
# To get the alias of the variable name
something_alias = SomeModel.__fields__["something"].alias
LOGGER.info(f"something_alias: {something_alias}")
# Edit: prefer to use "parsed_body_by_alias" than raw_body. Leaving here to show the difference.
raw_body: bytes = await request.body()
LOGGER.info(f"raw_body: {raw_body}")
# Edit: This is better as you get validated / parsed values, including defaults if applicable.
parsed_body_by_alias = parsed_body.dict(by_alias=True)
LOGGER.info(f"parsed_body_by_alias: {parsed_body_by_alias}")
# If you just want "something" instead of "$something"
LOGGER.info(f"parsed_body: {parsed_body}")
LOGGER.info(f"parsed_body.something: {parsed_body.something}")
return 1
if __name__ == "__main__":
import uvicorn
uvicorn.run(app, host="127.0.0.1", port=8080)
如果您 运行 代码然后发送 POST 正文:
{"$something": "bar"}
您会看到如下内容:
INFO xxx - __main__ - SomeModel.__fields__: {'something': ModelField(name='something', type=Optional[str], required=False, default=None, alias='$something')}
INFO xxx - __main__ - something_alias: $something
INFO xxx - __main__ - raw_body: b'{"$something": "bar"}'
INFO xxx - __main__ - parsed_body_by_alias: {'$something': 'bar'}
INFO xxx - __main__ - parsed_body: something='bar'
INFO xxx - __main__ - parsed_body.something: bar
INFO: 127.0.0.1:xxxxx - "POST / HTTP/1.1" 200 OK