FastAPI と Tortoise-ORM を使用しているときに、ForeignKey 関係を使用して json で返す方法は?
TortoiseORM を直接使用してそれらを実装する方法は知っていますが、FastAPI で同じことをしようとすると失敗します。私のスキーマには関係が表示されません。また、HTTP/JSON を介してこの情報を表すためにオブジェクトを作成/更新する方法もわかりません。
以下は、単純なモデル (2 つの要素、単純なリレーションシップ、およびオブジェクトを取得/配置/投稿するための FastAPI ボイラー プレート全体) を使用した小さな実行コードに従います。コードは、最初tortoise-orm
fastapi
に とをインストールする必要がありますuvicorn
。そうでない場合、呼び出しは失敗します) python main.py
。main.py
uvicorn.run
# Requires: tortoise-orm, fastapi, uvicorn
from typing import List
import Tortoise
from fastapi import FastAPI
from tortoise.models import Model
from tortoise.fields import (
IntField,
CharField,
ForeignKeyField,
DatetimeField,
ReverseRelation,
)
from tortoise.contrib.fastapi import register_tortoise
from tortoise.contrib.pydantic.creator import (
pydantic_model_creator,
pydantic_queryset_creator,
)
class Toy(Model):
id = IntField(pk=True)
name = CharField(max_length=32, null=False)
owner = ForeignKeyField("models.Person", null=True, related_name="toys_own")
created_at = DatetimeField(auto_now_add=True)
updated_at = DatetimeField(auto_now=True)
class Person(Model):
id = IntField(pk=True)
name = CharField(max_length=32, null=False)
toys_own: ReverseRelation["Toy"]
ToySchema = pydantic_model_creator(Toy, name="Toy")
ToySchemaIn = pydantic_model_creator(Toy, name="ToyIn", exclude_readonly=True)
ToySchema_List = pydantic_queryset_creator(Toy)
PersonSchema = pydantic_model_creator(Person, name="Person")
PersonSchemaIn = pydantic_model_creator(Person, name="PersonIn", exclude_readonly=True)
PersonSchema_List = pydantic_queryset_creator(Person)
app = FastAPI()
async def init():
Tortoise.init_models(["main"], "models")
register_tortoise(
app,
db_url="sqlite://:memory:",
modules={"models": ["main"]},
generate_schemas=True,
add_exception_handlers=True,
)
print(ToySchema.schema_json(indent=4))
print(PersonSchema.schema_json(indent=4))
@app.on_event("startup")
async def startup_event():
await init()
@app.get("/toy/{toy_id}", response_model=ToySchema)
async def get_toy(toy_id: int):
return await Toy.get(id=toy_id)
@app.get("/toy/", response_model=List[ToySchema])
async def get_all_toys():
return await Toy.all()
@app.post("/toy", response_model=ToySchema)
async def create_toy(toy: ToySchemaIn):
return await Toy.create(**toy.dict(exclude_unset=True))
@app.put("/toy/{toy_id}", response_model=ToySchema)
async def update_toy(toy_id: int, toy: ToySchemaIn):
await Toy.filter(id=toy_id).update(**toy.dict(exclude_unset=True))
return await Toy.get(id=toy_id)
@app.get("/person/{person_id}", response_model=PersonSchema)
async def get_person(person_id: int):
return await PersonSchema.from_queryset_single(Person.get(id=person_id))
@app.get("/person/", response_model=List[PersonSchema])
async def get_all_persons():
return await PersonSchema.from_queryset(Person.all())
@app.post("/person", response_model=PersonSchema)
async def create_person(person: PersonSchemaIn):
person_ = await Person.create(**person.dict(exclude_unset=True))
return await PersonSchema.from_tortoise_orm(person_)
@app.put("/person/{person_id}", response_model=PersonSchema)
async def update_person(person_id: int, person: PersonSchemaIn):
await Person.filter(id=person_id).update(**person.dict(exclude_unset=True))
return await PersonSchema.from_queryset_single(Person.get(id=person_id))
if __name__ == "__main__":
import uvicorn
uvicorn.run("main:app", host="127.0.0.1", port=8888, reload=True)
また、より簡単なテストのために、いくつかのオブジェクトを作成/更新するための小さな bash スクリプトをフォローアップします。
echo -e "\n\nCreate one toy: "
curl -X 'POST' \
'http://127.0.0.1:8888/toy' \
-H 'accept: application/json' \
-H 'Content-Type: application/json' \
-d "{
\"name\": \"Pinocchio ${RANDOM}\"
}"
echo -e "\n\nUPDATE one toy: "
curl -X 'PUT' \
'http://127.0.0.1:8888/toy/1' \
-H 'accept: application/json' \
-H 'Content-Type: application/json' \
-d "{
\"name\": \"SidEdit ${RANDOM}\"
}"
echo -e "\n\nGet all toys"
curl -X 'GET' \
'http://127.0.0.1:8888/toy/' \
-H 'accept: application/json'
echo -e "\n\nCreate one person: "
curl -X 'POST' \
'http://127.0.0.1:8888/person' \
-H 'accept: application/json' \
-H 'Content-Type: application/json' \
-d "{
\"name\": \"John ${RANDOM}\"
}"
echo -e "\n\nUPDATE one person: "
curl -X 'PUT' \
'http://127.0.0.1:8888/person/1' \
-H 'accept: application/json' \
-H 'Content-Type: application/json' \
-d "{
\"name\": \"MaryEdit ${RANDOM}\"
}"
echo -e "\n\nGet all persons"
curl -X 'GET' \
'http://127.0.0.1:8888/person/' \
-H 'accept: application/json'
このスニペットは、Python 3.9、Tortoise ORM 0.17.8、および FastAPI 0.70.0 で正常に動作します。