1

FastAPI と Tortoise-ORM を使用しているときに、ForeignKey 関係を使用して json で返す方法は?

TortoiseORM を直接使用してそれらを実装する方法は知っていますが、FastAPI で同じことをしようとすると失敗します。私のスキーマには関係が表示されません。また、HTTP/JSON を介してこの情報を表すためにオブジェクトを作成/更新する方法もわかりません。

以下は、単純なモデル (2 つの要素、単純なリレーションシップ、およびオブジェクトを取得/配置/投稿するための FastAPI ボイラー プレート全体) を使用した小さな実行コードに従います。コードは、最初tortoise-orm fastapiに とをインストールする必要がありますuvicorn。そうでない場合、呼び出しは失敗します) python main.pymain.pyuvicorn.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 で正常に動作します。

4

0 に答える 0