読者コミュニティ|FastAPI入門
本の感想や質問をお気軽にコメントしてください。
・誤りの指摘
・こういう内容を追加して欲しい
など忌憚なきご意見をお待ちしております!
こんにちは
FastAPIのサンプルを探していて、とても勉強になりました。
いくつかエラーになった箇所をお知らせします。
- 9章 api/routers/task.py GETのサンプルに
from typing import List
がありません。 - 10章 api/schemas/task.py
class Task(BaseModel):
→class Task(TaskBase):
に修正する内容が記載されていません。(最終的なソースがあるので、見比べるとわかります) - 11章 間違っているわけではないのですが、M1 macだと1行追加が必要でした。
db:
image: mysql:8.0
platform: linux/x86_64. ←この行を追加
environment:
- 11章 api/migrate_db.py に
from api.models.task import Task, Done
がありません。 - 12章 api/routers/task.pyのPOSTのサンプルに
from fastapi import APIRouter, Depends
とDepends
のインポートが必要です。
ここから要望です。
- テストの実行コマンドを追記して欲しいです。
$ docker-compose exec demo-app poetry run Pytest tests
で確認できました。 - 本番環境で稼働させる前提の書き方が知りたいです。データベースの接続URLなどを環境変数に持たせるなどです。
- CORSなどセキュリティー関係の設定があると嬉しいです。
- 続編でも良いですが、クラウドのサーバ構築、CI/CDがあると嬉しいです。
- これも続編でも良いですが、アクセスログなど本番環境で稼働させる場合のログ出力の情報があると嬉しいです。
フィードバックいただきありがとうございます!
ご指摘の点、的確かつ詳細に記載いただきありがとうございました。取り急ぎ修正させていただきました!🙇
11章 api/migrate_db.py にfrom api.models.task import Task, Doneがありません。
こちらコード的には不要かと思うのですが、エラー内容いただけますと幸いです。
要望についてもありがとうございます。続編も考えておりましたので大変励みになります。一部本書にも反映させていただくかもしれません!他にもございましたら遠慮なくお願いします。
11章 api/migrate_db.py にfrom api.models.task import Task, Doneがありません。
こちらコード的には不要かと思うのですが、エラー内容いただけますと幸いです。
import順によって Task
および Done
クラスが認識されない場合があるようです。
以下のように修正いたしました!
< from api.db import Base
> from api.models.task import Base
Chapter 09 : スキーマ(Schemas) - レスポンスにおいて、api/routers/task.pyの書き換えの際に
from fastapi import APIRouter
が抜けている気がしますが、いかがでしょうか?
フィードバックありがとうございます!
修正いたしました。
1)
from fastapi import APIRouter
from fastapi import APIRouter, Depends
の部分+/-が逆のようです
NameError: name 'AsyncSession' is not defined
というエラーがでていたので、
from sqlalchemy.ext.asyncio import AsyncSession
という行を足したらエラーはでなくなりました。
ご指摘ありがとうございます。修正しました!
こんにちわ
とてもわかりやすい内容でした!
書籍化してみませんか?
ご連絡おまちしております!
ご連絡ありがとうございます。
それではTwitterにてご連絡いたします。
takabonというハンドルネームです。
こんにちは。
勉強したいと思っていた内容をわかりやすく書いていただき、ありがとうございます。
一通り自分でもコードを書きながら読ませていただいています。
1点、自身で解決できていないエラーがあるため質問させていただいてもよろしいでしょうか?
13章ユニットテストでテストを実行した際、
============================================================== short test summary info ===============================================================
FAILED tests/test_main.py::test_create_and_read - AttributeError: 'async_generator' object has no attribute 'post'
FAILED tests/test_main.py::test_done_flag - AttributeError: 'async_generator' object has no attribute 'post'
================================================================= 2 failed in 0.52s ==================================================================
ERROR: 1
というように、
AttributeError: 'async_generator' object has no attribute 'post'
が出てしまいます。async_generatorについても調べてみましたが、自己解決できておりません。
アドバイスいただけると幸いです。
使われている pytest-asyncio
のバージョンはいくつでしょうか?(pyproject.tomlからわかります)
>=0.19
であれば、fixtureの指定方法が デフォルトで変わっている ようです。以下のように指定すると、パスするかもしれません。
$ pytest tests --asyncio-mode=auto
アドバイスしていただきありがとうございます。
pytest-asynco
のバージョンは0.19.0
です。
$ pytest tests --asyncio-mode=auto
を実行しましたが、
コマンド 'pytest' が見つかりません。
と表示されます。
そのため、以下のコマンドを実行しました。
$ docker-compose run --entrypoint "pytest tests --asyncio-mode=auto" demo-app
しかしながら、下記のエラーが出ました。
Error response from daemon: failed to create shim task:
OCI runtime create failed: runc create failed:
unable to start container process: exec:
"pytest": executable file not found in $PATH: unknown
再度、アドバイスいただけますと幸いです。
0.19.0
でしたらちょうど pytest-asyncio
のバージョンが変更されたところなので、こちらの方法で解決できるかと思います。
poetryを利用してpytestを実行しているので、 poetry run
が必要になります。本書に沿ったコマンドは以下となります。
$ docker-compose run --entrypoint "poetry run pytest --asyncio-mode=auto" demo-app
早速のアドバイスありがとうございます。
質問させていただいたエラーは解決できました。
ありがとうございました。
しかしながら、
FAILED tests/test_main.py::test_create_and_read - AttributeError: module 'api.schemas.task' has no attribute 'dict'
FAILED tests/test_main.py::test_done_flag - AttributeError: module 'api.schemas.task' has no attribute 'dict'
のエラーが出たので、私のコード入力が間違っているのだと思います。
確認のため、コード一式が確認できるリンク等をご教授いただけますでしょうか。
pytest-asyncioのエラーが解消されたようで良かったです。
なお、現在コードベース全体は公開していない状態です、ご容赦ください。
エラーのスタックトレースを貼っていただければある程度お力添えできるかもしれません。
はじめまして。
FastAPIを含め、プログラミングはまだまだ初学者です。
このFastAPIの入門書を見つけて、同じようにコードを書いていましたが、手順どおりに進めていくと、uvicornは起動するもののファイルを保存しても--reloadが実行されませんでした。
docker-composeの設定なのか、フォルダ構成の問題なのか、はたまた他の問題なのかが分かりませんでした。
なにか設定等で必要なことがあれば教えていただけないでしょうか。
質問の仕方もどうしたらよいかわからなかったため、とりあえず書かせていただきました。
よろしくお願いいたします。
docker-compose up
を実行しても こちら のようにSwagger UIが表示されない状態でしょうか?あるいは、ファイルを追加で上書きしても、reloadが走らないということでしょうか?
前者であれば、エラーメッセージを貼って頂ければ何かお力添えできるかもしれません。
ありがとうございます。
詳細をお伝えすると、Windows PCでの実行をしようとしています。
同じ設定で記述しましたので、Swagger UIの表示はされます。
ですが、main.py等のファイルを上書きしてもreloadされず、返されるjsonの各値が変更にならない状態です。
何度やってもダメでした。
requirements.txtでやると上手くいく時があり、poetryが原因かとも疑いましたが、原因不明です。
Macで実行すると問題なく起動します。
横から失礼いたします。
似たような問題でdockerのホットリロード関係が原因だったことがあり、もしかしたらそれかなという共有でした。(的外れでしたらすみません)
docker-compose run --entrypoint "poetry install" demo-app
実行後に
/src/demo_app does not contain any element
とエラー表示されるのですがどういったエラーでしょうか?
同じエラーでましたが、こちらでいけました!
ありがとうございます😭
初学者の質問で申し訳ありません。私も同じところにハマってしまい、なんやかんやで抜け出せたのですが、自分が行った手順の何が正しかったのかをいまいち理解していないためどなたかご教授いただけませんでしょうか。。
やったこと
Dockerfileの修正
# poetryでライブラリをインストール (pyproject.tomlが既にある場合)
RUN poetry config virtualenvs.in-project true
- RUN if [ -f pyproject.toml ]; then poetry install; fi
+ RUN if [ -f pyproject.toml ]; then poetry install --no-root; fi
# uvicornのサーバーを立ち上げる
ターミナルで実行したコマンドの修正
- docker-compose run --entrypoint "poetry install" demo-app
+ docker-compose run --entrypoint "poetry install --no-root" demo-app
コメントありがとうございます。当初執筆時のpoetryのバージョンが1.1.2と古かったのですが、現行のpoetryでは poetry init
時に packages = [{include = "demo_app"}]
が含まれるようになり、 poetry install
した際に、デフォルトでプロジェクト自身をインストールしようとします。
「FastAPI入門」ではプロジェクト自身をpoetryでインストールする必要がないため、 poetry install
時に --no-root
オプションを渡すことでプロジェクトをパッケージとしてインストールするステップがスキップされ、エラーなくインストールを進めることが可能です。(MAAAAAAAAAAAさんのコメントの通りの変更で問題有りません)
記事の方にも反映しておきました。
説明とご対応ありがとうございます🙇
僕の環境で詰まった場所と、その解決策を共有します。
環境(OS)
- ubuntu-22.04 (Windows11のwsl2上で動作)
完了フラグがtrueのタスクをdeleteできない
これは、MySQLの外部キー制約で、消したいtablesテーブルの列のid要素がdonesテーブルに存在する場合にエラーが発生したためである。
DELETE CASCADEを設定することで直った。
from sqlalchemy import Column, Integer, String, ForeignKey
from sqlalchemy.orm import relationship
from api.db import Base
class Task(Base):
__tablename__ = "tasks"
id = Column(Integer, primary_key=True)
title = Column(String(1024))
+ done = relationship("Done", back_populates="task", cascade="delete")
- done = relationship("Done", back_populates="task")
class Done(Base):
__tablename__ = "dones"
+ id = Column(Integer, ForeignKey("tasks.id", ondelete="CASCADE"), primary_key=True)
- id = Column(Integer, ForeignKey("tasks.id"), primary_key=True)
task = relationship("Task", back_populates="done")
ご報告ありがとうございます!
仰るとおりですね。doneフラグが立っている(doneテーブルにレコードがある)際のみDELETEエラーとなるので見落としておりました。
ForeignKeyの変更ですとmigration時に ON DELETE CASCADE
がforeign keyに付与されるのですが、これだけですと削除時のエラーは改善しませんでした。一方で、relationshipにcascadeオプションを設定した場合、SQLAlchemyのレイヤーで解決してくれるので、こちらを採用し、 Chapter 11 に反映いたしました。
初めまして。
プログラミング初心者です。
smithonisanのFastAPI入門の、poetryによるPython環境のセットアップで詰まってしまいました。
$ docker-compose run
--entrypoint "poetry init
--name demo-app
--dependency fastapi
--dependency uvicorn[standard]"
demo-app
↑このコードでエラーが出てしまいました。
エラーコードは↓
発生場所 行:1 文字:5
- --entrypoint "poetry init \
-
~
単項演算子 '--' の後に式が存在しません。
発生場所 行:1 文字:5
- --entrypoint "poetry init \
-
~~~~~~~~~~
式またはステートメントのトークン 'entrypoint' を使用できません。
+ CategoryInfo : ParserError: (:) [], ParentContainsErrorRe
cordException
+ FullyQualifiedErrorId : MissingExpressionAfterOperator
改善方法のご教授お願いします。(´;ω;`)
コメント頂いていたのに気づくのが遅くなってしまいました。申し訳ございません。
エラー内容を拝見するに、PowerShellをお使いでしょうか?コマンドはシェルスクリプト(Unixシェル)を想定しておりました。PowerShellの場合はコマンドの改行に \
(back slash) ではなく ` (back quote) を利用するということです。こちらに読み替えた上でお試し頂けるでしょうか?
はじめまして。
大変勉強になる本をありがとうございます。
Chapter 10 「スキーマ(Schemas) - リクエスト」の「ルーター」セクションでの記述について質問です。
ここで、
dict
インスタンスに対して先頭に**
をつけることで、dict
を キーワード引数として展開 し、task_schema.TaskCreateResponse
クラスのコンストラクタに対してdict
のkey/valueを渡します。
つまり、これはtask_schema.TaskCreateResponse(id=1, title=task_body.title, done=task_body.done)
と等価となります。
「task_schema.TaskCreateResponse(id=1, title=task_body.title, done=task_body.done)
と等価となります。」という記述がありますが、正しくは task_schema.TaskCreateResponse(id=1, title=task_body.title)
ではないかと考えました。
**
を用いて展開している、パスオペレーション関数 create_task()
の引数 task_doby
の型は task_schema.TaskCreate
であり、 done
フラグが存在しないのではないかと思いました。
どなたかのお考えをお聞かせいただけますと幸いです。
コメントありがとうございます。
ご指摘の通りかと思います。以下のように本文の変更を行いました。
つまり、これは task_schema.TaskCreateResponse(id=1, title=task_body.title) と等価となります。なお、ここではクラスの持つインスタンス変数が1つのため ** を利用するメリットが見えづらいですが、変数が多い場合にすべてを羅列せずに済みます。
分かりやすくコンパクトにまとまっていてとてもためになりました。
最新の環境でユニットテストが実行できないようになっているようです。
下記のように修正したら動きました。
+ import pytest, pytest_asyncio
- import pytest
+ from httpx import AsyncClient, ASGITransport
- from httpx import AsyncClient
...
+ @pytest_asyncio.fixture
- @pytest.fixture
...
# テスト用に非同期HTTPクライアントを返却
+ transport = ASGITransport(app=app)
+ async with AsyncClient(transport=transport, base_url="http://test") as client:
- async with AsyncClient(app=app, base_url="http://test") as client: