169 changed files with 14944 additions and 1083 deletions
@ -1,16 +1,24 @@ |
|||
# FastAPI bei Cloudanbietern bereitstellen { #deploy-fastapi-on-cloud-providers } |
|||
# FastAPI bei Cloudanbietern deployen { #deploy-fastapi-on-cloud-providers } |
|||
|
|||
Sie können praktisch **jeden Cloudanbieter** verwenden, um Ihre FastAPI-Anwendung bereitzustellen. |
|||
|
|||
In den meisten Fällen bieten die großen Cloudanbieter Anleitungen zum Bereitstellen von FastAPI an. |
|||
In den meisten Fällen bieten die großen Cloudanbieter Anleitungen zum Deployment von FastAPI an. |
|||
|
|||
## Cloudanbieter – Sponsoren { #cloud-providers-sponsors } |
|||
## FastAPI Cloud { #fastapi-cloud } |
|||
|
|||
**<a href="https://fastapicloud.com" class="external-link" target="_blank">FastAPI Cloud</a>** wurde vom selben Autor und Team hinter **FastAPI** entwickelt. |
|||
|
|||
Es vereinfacht den Prozess des **Erstellens**, **Deployens** und **Zugreifens** auf eine API mit minimalem Aufwand. |
|||
|
|||
Einige Cloudanbieter ✨ [**sponsern FastAPI**](../help-fastapi.md#sponsor-the-author){.internal-link target=_blank} ✨, dies stellt die kontinuierliche und gesunde **Entwicklung** von FastAPI und seinem **Ökosystem** sicher. |
|||
Es bringt die gleiche **Developer-Experience** beim Erstellen von Apps mit FastAPI auch zum **Deployment** in der Cloud. 🎉 |
|||
|
|||
FastAPI Cloud ist der Hauptsponsor und Finanzierungsgeber für die *FastAPI and friends* Open-Source-Projekte. ✨ |
|||
|
|||
## Cloudanbieter – Sponsoren { #cloud-providers-sponsors } |
|||
|
|||
Und es zeigt ihr wahres Engagement für FastAPI und seine **Community** (Sie), da sie Ihnen nicht nur einen **guten Service** bieten möchten, sondern auch sicherstellen möchten, dass Sie ein **gutes und gesundes Framework**, FastAPI, haben. 🙇 |
|||
Einige andere Cloudanbieter ✨ [**sponsern FastAPI**](../help-fastapi.md#sponsor-the-author){.internal-link target=_blank} ✨ ebenfalls. 🙇 |
|||
|
|||
Vielleicht möchten Sie deren Dienste ausprobieren und deren Anleitungen folgen: |
|||
Sie könnten diese ebenfalls in Betracht ziehen, deren Anleitungen folgen und ihre Dienste ausprobieren: |
|||
|
|||
* <a href="https://docs.render.com/deploy-fastapi?utm_source=deploydoc&utm_medium=referral&utm_campaign=fastapi" class="external-link" target="_blank">Render</a> |
|||
* <a href="https://docs.railway.com/guides/fastapi?utm_medium=integration&utm_source=docs&utm_campaign=fastapi" class="external-link" target="_blank">Railway</a> |
|||
|
|||
@ -0,0 +1,65 @@ |
|||
# FastAPI Cloud { #fastapi-cloud } |
|||
|
|||
Sie können Ihre FastAPI-App in der <a href="https://fastapicloud.com" class="external-link" target="_blank">FastAPI Cloud</a> mit **einem einzigen Befehl** deployen – tragen Sie sich in die Warteliste ein, falls noch nicht geschehen. 🚀 |
|||
|
|||
## Anmelden { #login } |
|||
|
|||
Stellen Sie sicher, dass Sie bereits ein **FastAPI-Cloud-Konto** haben (wir haben Sie von der Warteliste eingeladen 😉). |
|||
|
|||
Melden Sie sich dann an: |
|||
|
|||
<div class="termy"> |
|||
|
|||
```console |
|||
$ fastapi login |
|||
|
|||
You are logged in to FastAPI Cloud 🚀 |
|||
``` |
|||
|
|||
</div> |
|||
|
|||
## Deployen { #deploy } |
|||
|
|||
Stellen Sie Ihre App jetzt mit **einem einzigen Befehl** bereit: |
|||
|
|||
<div class="termy"> |
|||
|
|||
```console |
|||
$ fastapi deploy |
|||
|
|||
Deploying to FastAPI Cloud... |
|||
|
|||
✅ Deployment successful! |
|||
|
|||
🐔 Ready the chicken! Your app is ready at https://myapp.fastapicloud.dev |
|||
``` |
|||
|
|||
</div> |
|||
|
|||
Das war’s! Jetzt können Sie Ihre App unter dieser URL aufrufen. ✨ |
|||
|
|||
## Über FastAPI Cloud { #about-fastapi-cloud } |
|||
|
|||
**<a href="https://fastapicloud.com" class="external-link" target="_blank">FastAPI Cloud</a>** wird vom gleichen Autor und Team hinter **FastAPI** entwickelt. |
|||
|
|||
Es vereinfacht den Prozess des **Erstellens**, **Deployens** und **Nutzens** einer API mit minimalem Aufwand. |
|||
|
|||
Es bringt die gleiche **Developer-Experience** beim Erstellen von Apps mit FastAPI auch zum **Deployment** in der Cloud. 🎉 |
|||
|
|||
Es kümmert sich außerdem um das meiste, was beim Deployen einer App nötig ist, zum Beispiel: |
|||
|
|||
* HTTPS |
|||
* Replikation, mit Autoscaling basierend auf Requests |
|||
* usw. |
|||
|
|||
FastAPI Cloud ist Hauptsponsor und Finanzierer der Open-Source-Projekte *FastAPI and friends*. ✨ |
|||
|
|||
## Bei anderen Cloudanbietern deployen { #deploy-to-other-cloud-providers } |
|||
|
|||
FastAPI ist Open Source und basiert auf Standards. Sie können FastAPI-Apps bei jedem Cloudanbieter Ihrer Wahl deployen. |
|||
|
|||
Folgen Sie den Anleitungen Ihres Cloudanbieters, um dort FastAPI-Apps zu deployen. 🤓 |
|||
|
|||
## Auf den eigenen Server deployen { #deploy-your-own-server } |
|||
|
|||
Ich werde Ihnen später in diesem **Deployment-Leitfaden** auch alle Details zeigen, sodass Sie verstehen, was passiert, was geschehen muss und wie Sie FastAPI-Apps selbst deployen können, auch auf Ihre eigenen Server. 🤓 |
|||
@ -0,0 +1,17 @@ |
|||
# Alte 403-Authentifizierungsfehler-Statuscodes verwenden { #use-old-403-authentication-error-status-codes } |
|||
|
|||
Vor FastAPI-Version `0.122.0` verwendeten die integrierten Sicherheits-Utilities den HTTP-Statuscode `403 Forbidden`, wenn sie dem Client nach einer fehlgeschlagenen Authentifizierung einen Fehler zurückgaben. |
|||
|
|||
Ab FastAPI-Version `0.122.0` verwenden sie den passenderen HTTP-Statuscode `401 Unauthorized` und geben in der Response einen sinnvollen `WWW-Authenticate`-Header zurück, gemäß den HTTP-Spezifikationen, <a href="https://datatracker.ietf.org/doc/html/rfc7235#section-3.1" class="external-link" target="_blank">RFC 7235</a>, <a href="https://datatracker.ietf.org/doc/html/rfc9110#name-401-unauthorized" class="external-link" target="_blank">RFC 9110</a>. |
|||
|
|||
Aber falls Ihre Clients aus irgendeinem Grund vom alten Verhalten abhängen, können Sie darauf zurückgreifen, indem Sie in Ihren Sicherheitsklassen die Methode `make_not_authenticated_error` überschreiben. |
|||
|
|||
Sie können beispielsweise eine Unterklasse von `HTTPBearer` erstellen, die einen Fehler `403 Forbidden` zurückgibt, statt des Default-`401 Unauthorized`-Fehlers: |
|||
|
|||
{* ../../docs_src/authentication_error_status_code/tutorial001_an_py39.py hl[9:13] *} |
|||
|
|||
/// tip | Tipp |
|||
|
|||
Beachten Sie, dass die Funktion die Exception-Instanz zurückgibt; sie wirft sie nicht. Das Werfen erfolgt im restlichen internen Code. |
|||
|
|||
/// |
|||
@ -1,3 +1,3 @@ |
|||
# Ressourcen { #resources } |
|||
|
|||
Zusätzliche Ressourcen, externe Links, Artikel und mehr. ✈️ |
|||
Zusätzliche Ressourcen, externe Links und mehr. ✈️ |
|||
|
|||
@ -1,430 +0,0 @@ |
|||
Articles: |
|||
English: |
|||
- author: Apitally |
|||
author_link: https://apitally.io |
|||
link: https://apitally.io/blog/getting-started-with-logging-in-fastapi |
|||
title: Getting started with logging in FastAPI |
|||
- author: Balthazar Rouberol |
|||
author_link: https://balthazar-rouberol.com |
|||
link: https://blog.balthazar-rouberol.com/how-to-profile-a-fastapi-asynchronous-request |
|||
title: How to profile a FastAPI asynchronous request |
|||
- author: Stephen Siegert - Neon |
|||
link: https://neon.tech/blog/deploy-a-serverless-fastapi-app-with-neon-postgres-and-aws-app-runner-at-any-scale |
|||
title: Deploy a Serverless FastAPI App with Neon Postgres and AWS App Runner at any scale |
|||
- author: Kurtis Pykes - NVIDIA |
|||
link: https://developer.nvidia.com/blog/building-a-machine-learning-microservice-with-fastapi/ |
|||
title: Building a Machine Learning Microservice with FastAPI |
|||
- author: Ravgeet Dhillon - Twilio |
|||
link: https://www.twilio.com/en-us/blog/booking-appointments-twilio-notion-fastapi |
|||
title: Booking Appointments with Twilio, Notion, and FastAPI |
|||
- author: Abhinav Tripathi - Microsoft Blogs |
|||
link: https://devblogs.microsoft.com/cosmosdb/azure-cosmos-db-python-and-fastapi/ |
|||
title: Write a Python data layer with Azure Cosmos DB and FastAPI |
|||
- author: Donny Peeters |
|||
author_link: https://github.com/Donnype |
|||
link: https://bitestreams.com/blog/fastapi-sqlalchemy/ |
|||
title: 10 Tips for adding SQLAlchemy to FastAPI |
|||
- author: Jessica Temporal |
|||
author_link: https://jtemporal.com/socials |
|||
link: https://jtemporal.com/tips-on-migrating-from-flask-to-fastapi-and-vice-versa/ |
|||
title: Tips on migrating from Flask to FastAPI and vice-versa |
|||
- author: Ankit Anchlia |
|||
author_link: https://linkedin.com/in/aanchlia21 |
|||
link: https://hackernoon.com/explore-how-to-effectively-use-jwt-with-fastapi |
|||
title: Explore How to Effectively Use JWT With FastAPI |
|||
- author: Nicoló Lino |
|||
author_link: https://www.nlino.com |
|||
link: https://github.com/softwarebloat/python-tracing-demo |
|||
title: Instrument FastAPI with OpenTelemetry tracing and visualize traces in Grafana Tempo. |
|||
- author: Mikhail Rozhkov, Elena Samuylova |
|||
author_link: https://www.linkedin.com/in/mnrozhkov/ |
|||
link: https://www.evidentlyai.com/blog/fastapi-tutorial |
|||
title: ML serving and monitoring with FastAPI and Evidently |
|||
- author: Visual Studio Code Team |
|||
author_link: https://code.visualstudio.com/ |
|||
link: https://code.visualstudio.com/docs/python/tutorial-fastapi |
|||
title: FastAPI Tutorial in Visual Studio Code |
|||
- author: Apitally |
|||
author_link: https://apitally.io |
|||
link: https://blog.apitally.io/fastapi-application-monitoring-made-easy |
|||
title: FastAPI application monitoring made easy |
|||
- author: John Philip |
|||
author_link: https://medium.com/@amjohnphilip |
|||
link: https://python.plainenglish.io/building-a-restful-api-with-fastapi-secure-signup-and-login-functionality-included-45cdbcb36106 |
|||
title: "Building a RESTful API with FastAPI: Secure Signup and Login Functionality Included" |
|||
- author: Keshav Malik |
|||
author_link: https://theinfosecguy.xyz/ |
|||
link: https://blog.theinfosecguy.xyz/building-a-crud-api-with-fastapi-and-supabase-a-step-by-step-guide |
|||
title: Building a CRUD API with FastAPI and Supabase |
|||
- author: Adejumo Ridwan Suleiman |
|||
author_link: https://www.linkedin.com/in/adejumoridwan/ |
|||
link: https://medium.com/python-in-plain-english/build-an-sms-spam-classifier-serverless-database-with-faunadb-and-fastapi-23dbb275bc5b |
|||
title: Build an SMS Spam Classifier Serverless Database with FaunaDB and FastAPI |
|||
- author: Raf Rasenberg |
|||
author_link: https://rafrasenberg.com/about/ |
|||
link: https://rafrasenberg.com/fastapi-lambda/ |
|||
title: 'FastAPI lambda container: serverless simplified' |
|||
- author: Teresa N. Fontanella De Santis |
|||
author_link: https://dev.to/ |
|||
link: https://dev.to/teresafds/authorization-on-fastapi-with-casbin-41og |
|||
title: Authorization on FastAPI with Casbin |
|||
- author: New Relic |
|||
author_link: https://newrelic.com |
|||
link: https://newrelic.com/instant-observability/fastapi/e559ec64-f765-4470-a15f-1901fcebb468 |
|||
title: How to monitor FastAPI application performance using Python agent |
|||
- author: Jean-Baptiste Rocher |
|||
author_link: https://hashnode.com/@jibrocher |
|||
link: https://dev.indooroutdoor.io/series/fastapi-react-poll-app |
|||
title: Building the Poll App From Django Tutorial With FastAPI And React |
|||
- author: Silvan Melchior |
|||
author_link: https://github.com/silvanmelchior |
|||
link: https://blog.devgenius.io/seamless-fastapi-configuration-with-confz-90949c14ea12 |
|||
title: Seamless FastAPI Configuration with ConfZ |
|||
- author: Kaustubh Gupta |
|||
author_link: https://medium.com/@kaustubhgupta1828/ |
|||
link: https://levelup.gitconnected.com/5-advance-features-of-fastapi-you-should-try-7c0ac7eebb3e |
|||
title: 5 Advanced Features of FastAPI You Should Try |
|||
- author: Kaustubh Gupta |
|||
author_link: https://medium.com/@kaustubhgupta1828/ |
|||
link: https://www.analyticsvidhya.com/blog/2021/06/deploying-ml-models-as-api-using-fastapi-and-heroku/ |
|||
title: Deploying ML Models as API Using FastAPI and Heroku |
|||
- link: https://jarmos.netlify.app/posts/using-github-actions-to-deploy-a-fastapi-project-to-heroku/ |
|||
title: Using GitHub Actions to Deploy a FastAPI Project to Heroku |
|||
author_link: https://jarmos.netlify.app/ |
|||
author: Somraj Saha |
|||
- author: "@pystar" |
|||
author_link: https://pystar.substack.com/ |
|||
link: https://pystar.substack.com/p/how-to-create-a-fake-certificate |
|||
title: How to Create A Fake Certificate Authority And Generate TLS Certs for FastAPI |
|||
- author: Ben Gamble |
|||
author_link: https://uk.linkedin.com/in/bengamble7 |
|||
link: https://ably.com/blog/realtime-ticket-booking-solution-kafka-fastapi-ably |
|||
title: Building a realtime ticket booking solution with Kafka, FastAPI, and Ably |
|||
- author: Shahriyar(Shako) Rzayev |
|||
author_link: https://www.linkedin.com/in/shahriyar-rzayev/ |
|||
link: https://www.azepug.az/posts/fastapi/#building-simple-e-commerce-with-nuxtjs-and-fastapi-series |
|||
title: Building simple E-Commerce with NuxtJS and FastAPI |
|||
- author: Rodrigo Arenas |
|||
author_link: https://rodrigo-arenas.medium.com/ |
|||
link: https://medium.com/analytics-vidhya/serve-a-machine-learning-model-using-sklearn-fastapi-and-docker-85aabf96729b |
|||
title: "Serve a machine learning model using Sklearn, FastAPI and Docker" |
|||
- author: Yashasvi Singh |
|||
author_link: https://hashnode.com/@aUnicornDev |
|||
link: https://aunicorndev.hashnode.dev/series/supafast-api |
|||
title: "Building an API with FastAPI and Supabase and Deploying on Deta" |
|||
- author: Navule Pavan Kumar Rao |
|||
author_link: https://www.linkedin.com/in/navule/ |
|||
link: https://www.tutlinks.com/deploy-fastapi-on-ubuntu-gunicorn-caddy-2/ |
|||
title: Deploy FastAPI on Ubuntu and Serve using Caddy 2 Web Server |
|||
- author: Patrick Ladon |
|||
author_link: https://dev.to/factorlive |
|||
link: https://dev.to/factorlive/python-facebook-messenger-webhook-with-fastapi-on-glitch-4n90 |
|||
title: Python Facebook messenger webhook with FastAPI on Glitch |
|||
- author: Valon Januzaj |
|||
author_link: https://www.linkedin.com/in/valon-januzaj-b02692187/ |
|||
link: https://valonjanuzaj.medium.com/deploy-a-dockerized-fastapi-application-to-aws-cc757830ba1b |
|||
title: Deploy a dockerized FastAPI application to AWS |
|||
- author: Amit Chaudhary |
|||
author_link: https://x.com/amitness |
|||
link: https://amitness.com/2020/06/fastapi-vs-flask/ |
|||
title: FastAPI for Flask Users |
|||
- author: Louis Guitton |
|||
author_link: https://x.com/louis_guitton |
|||
link: https://guitton.co/posts/fastapi-monitoring/ |
|||
title: How to monitor your FastAPI service |
|||
- author: Precious Ndubueze |
|||
author_link: https://medium.com/@gabbyprecious2000 |
|||
link: https://medium.com/@gabbyprecious2000/creating-a-crud-app-with-fastapi-part-one-7c049292ad37 |
|||
title: Creating a CRUD App with FastAPI (Part one) |
|||
- author: Farhad Malik |
|||
author_link: https://medium.com/@farhadmalik |
|||
link: https://towardsdatascience.com/build-and-host-fast-data-science-applications-using-fastapi-823be8a1d6a0 |
|||
title: Build And Host Fast Data Science Applications Using FastAPI |
|||
- author: Navule Pavan Kumar Rao |
|||
author_link: https://www.linkedin.com/in/navule/ |
|||
link: https://www.tutlinks.com/deploy-fastapi-on-azure/ |
|||
title: Deploy FastAPI on Azure App Service |
|||
- author: Davide Fiocco |
|||
author_link: https://github.com/davidefiocco |
|||
link: https://davidefiocco.github.io/streamlit-fastapi-ml-serving/ |
|||
title: Machine learning model serving in Python using FastAPI and streamlit |
|||
- author: Netflix |
|||
author_link: https://netflixtechblog.com/ |
|||
link: https://netflixtechblog.com/introducing-dispatch-da4b8a2a8072 |
|||
title: Introducing Dispatch |
|||
- author: Stavros Korokithakis |
|||
author_link: https://x.com/Stavros |
|||
link: https://www.stavros.io/posts/fastapi-with-django/ |
|||
title: Using FastAPI with Django |
|||
- author: Twilio |
|||
author_link: https://www.twilio.com |
|||
link: https://www.twilio.com/blog/build-secure-twilio-webhook-python-fastapi |
|||
title: Build a Secure Twilio Webhook with Python and FastAPI |
|||
- author: Sebastián Ramírez (tiangolo) |
|||
author_link: https://x.com/tiangolo |
|||
link: https://dev.to/tiangolo/build-a-web-api-from-scratch-with-fastapi-the-workshop-2ehe |
|||
title: Build a web API from scratch with FastAPI - the workshop |
|||
- author: Paul Sec |
|||
author_link: https://x.com/PaulWebSec |
|||
link: https://paulsec.github.io/posts/fastapi_plus_zeit_serverless_fu/ |
|||
title: FastAPI + Zeit.co = 🚀 |
|||
- author: cuongld2 |
|||
author_link: https://dev.to/cuongld2 |
|||
link: https://dev.to/cuongld2/build-simple-api-service-with-python-fastapi-part-1-581o |
|||
title: Build simple API service with Python FastAPI — Part 1 |
|||
- author: Paurakh Sharma Humagain |
|||
author_link: https://x.com/PaurakhSharma |
|||
link: https://dev.to/paurakhsharma/microservice-in-python-using-fastapi-24cc |
|||
title: Microservice in Python using FastAPI |
|||
- author: Guillermo Cruz |
|||
author_link: https://wuilly.com/ |
|||
link: https://wuilly.com/2019/10/real-time-notifications-with-python-and-postgres/ |
|||
title: Real-time Notifications with Python and Postgres |
|||
- author: Navule Pavan Kumar Rao |
|||
author_link: https://www.linkedin.com/in/navule/ |
|||
link: https://www.tutlinks.com/create-and-deploy-fastapi-app-to-heroku/ |
|||
title: Create and Deploy FastAPI app to Heroku without using Docker |
|||
- author: Arthur Henrique |
|||
author_link: https://x.com/arthurheinrique |
|||
link: https://medium.com/@arthur393/another-boilerplate-to-fastapi-azure-pipeline-ci-pytest-3c8d9a4be0bb |
|||
title: 'Another Boilerplate to FastAPI: Azure Pipeline CI + Pytest' |
|||
- author: Shane Soh |
|||
author_link: https://medium.com/@shane.soh |
|||
link: https://medium.com/analytics-vidhya/deploy-machine-learning-models-with-keras-fastapi-redis-and-docker-4940df614ece |
|||
title: Deploy Machine Learning Models with Keras, FastAPI, Redis and Docker |
|||
- author: Mandy Gu |
|||
author_link: https://towardsdatascience.com/@mandygu |
|||
link: https://towardsdatascience.com/deploying-iris-classifications-with-fastapi-and-docker-7c9b83fdec3a |
|||
title: 'Towards Data Science: Deploying Iris Classifications with FastAPI and Docker' |
|||
- author: Michael Herman |
|||
author_link: https://testdriven.io/authors/herman |
|||
link: https://testdriven.io/blog/fastapi-crud/ |
|||
title: 'TestDriven.io: Developing and Testing an Asynchronous API with FastAPI and Pytest' |
|||
- author: Bernard Brenyah |
|||
author_link: https://medium.com/@bbrenyah |
|||
link: https://medium.com/python-data/how-to-deploy-tensorflow-2-0-models-as-an-api-service-with-fastapi-docker-128b177e81f3 |
|||
title: How To Deploy Tensorflow 2.0 Models As An API Service With FastAPI & Docker |
|||
- author: Dylan Anthony |
|||
author_link: https://dev.to/dbanty |
|||
link: https://dev.to/dbanty/why-i-m-leaving-flask-3ki6 |
|||
title: Why I'm Leaving Flask |
|||
- author: Mike Moritz |
|||
author_link: https://medium.com/@mike.p.moritz |
|||
link: https://medium.com/@mike.p.moritz/using-docker-compose-to-deploy-a-lightweight-python-rest-api-with-a-job-queue-37e6072a209b |
|||
title: Using Docker Compose to deploy a lightweight Python REST API with a job queue |
|||
- author: '@euri10' |
|||
author_link: https://gitlab.com/euri10 |
|||
link: https://gitlab.com/euri10/fastapi_cheatsheet |
|||
title: A FastAPI and Swagger UI visual cheatsheet |
|||
- author: Uber Engineering |
|||
author_link: https://eng.uber.com |
|||
link: https://eng.uber.com/ludwig-v0-2/ |
|||
title: 'Uber: Ludwig v0.2 Adds New Features and Other Improvements to its Deep Learning Toolbox [including a FastAPI server]' |
|||
- author: Maarten Grootendorst |
|||
author_link: https://www.linkedin.com/in/mgrootendorst/ |
|||
link: https://towardsdatascience.com/how-to-deploy-a-machine-learning-model-dc51200fe8cf |
|||
title: How to Deploy a Machine Learning Model |
|||
- author: Johannes Gontrum |
|||
author_link: https://x.com/gntrm |
|||
link: https://medium.com/@gntrm/jwt-authentication-with-fastapi-and-aws-cognito-1333f7f2729e |
|||
title: JWT Authentication with FastAPI and AWS Cognito |
|||
- author: Ankush Thakur |
|||
author_link: https://geekflare.com/author/ankush/ |
|||
link: https://geekflare.com/python-asynchronous-web-frameworks/ |
|||
title: Top 5 Asynchronous Web Frameworks for Python |
|||
- author: Nico Axtmann |
|||
author_link: https://www.linkedin.com/in/nico-axtmann |
|||
link: https://medium.com/@nico.axtmann95/deploying-a-scikit-learn-model-with-onnx-und-fastapi-1af398268915 |
|||
title: Deploying a scikit-learn model with ONNX and FastAPI |
|||
- author: Nils de Bruin |
|||
author_link: https://medium.com/@nilsdebruin |
|||
link: https://medium.com/data-rebels/fastapi-authentication-revisited-enabling-api-key-authentication-122dc5975680 |
|||
title: 'FastAPI authentication revisited: Enabling API key authentication' |
|||
- author: Nick Cortale |
|||
author_link: https://nickc1.github.io/ |
|||
link: https://nickc1.github.io/api,/scikit-learn/2019/01/10/scikit-fastapi.html |
|||
title: 'FastAPI and Scikit-Learn: Easily Deploy Models' |
|||
- author: Errieta Kostala |
|||
author_link: https://dev.to/errietta |
|||
link: https://dev.to/errietta/introduction-to-the-fastapi-python-framework-2n10 |
|||
title: Introduction to the fastapi python framework |
|||
- author: Nils de Bruin |
|||
author_link: https://medium.com/@nilsdebruin |
|||
link: https://medium.com/data-rebels/fastapi-how-to-add-basic-and-cookie-authentication-a45c85ef47d3 |
|||
title: FastAPI — How to add basic and cookie authentication |
|||
- author: Nils de Bruin |
|||
author_link: https://medium.com/@nilsdebruin |
|||
link: https://medium.com/data-rebels/fastapi-google-as-an-external-authentication-provider-3a527672cf33 |
|||
title: FastAPI — Google as an external authentication provider |
|||
- author: William Hayes |
|||
author_link: https://medium.com/@williamhayes |
|||
link: https://medium.com/@williamhayes/fastapi-starlette-debug-vs-prod-5f7561db3a59 |
|||
title: FastAPI/Starlette debug vs prod |
|||
- author: Mukul Mantosh |
|||
author_link: https://x.com/MantoshMukul |
|||
link: https://www.jetbrains.com/pycharm/guide/tutorials/fastapi-aws-kubernetes/ |
|||
title: Developing FastAPI Application using K8s & AWS |
|||
- author: KrishNa |
|||
author_link: https://medium.com/@krishnardt365 |
|||
link: https://medium.com/@krishnardt365/fastapi-docker-and-postgres-91943e71be92 |
|||
title: Fastapi, Docker(Docker compose) and Postgres |
|||
- author: Devon Ray |
|||
author_link: https://devonray.com |
|||
link: https://devonray.com/blog/deploying-a-fastapi-project-using-aws-lambda-aurora-cdk |
|||
title: Deployment using Docker, Lambda, Aurora, CDK & GH Actions |
|||
- author: Shubhendra Kushwaha |
|||
author_link: https://www.linkedin.com/in/theshubhendra/ |
|||
link: https://theshubhendra.medium.com/mastering-soft-delete-advanced-sqlalchemy-techniques-4678f4738947 |
|||
title: 'Mastering Soft Delete: Advanced SQLAlchemy Techniques' |
|||
- author: Shubhendra Kushwaha |
|||
author_link: https://www.linkedin.com/in/theshubhendra/ |
|||
link: https://theshubhendra.medium.com/role-based-row-filtering-advanced-sqlalchemy-techniques-733e6b1328f6 |
|||
title: 'Role based row filtering: Advanced SQLAlchemy Techniques' |
|||
German: |
|||
- author: Marcel Sander (actidoo) |
|||
author_link: https://www.actidoo.com |
|||
link: https://www.actidoo.com/de/blog/python-fastapi-domain-driven-design |
|||
title: Domain-driven Design mit Python und FastAPI |
|||
- author: Nico Axtmann |
|||
author_link: https://x.com/_nicoax |
|||
link: https://blog.codecentric.de/2019/08/inbetriebnahme-eines-scikit-learn-modells-mit-onnx-und-fastapi/ |
|||
title: Inbetriebnahme eines scikit-learn-Modells mit ONNX und FastAPI |
|||
- author: Felix Schürmeyer |
|||
author_link: https://hellocoding.de/autor/felix-schuermeyer/ |
|||
link: https://hellocoding.de/blog/coding-language/python/fastapi |
|||
title: REST-API Programmieren mittels Python und dem FastAPI Modul |
|||
Japanese: |
|||
- author: '@bee2' |
|||
author_link: https://qiita.com/bee2 |
|||
link: https://qiita.com/bee2/items/75d9c0d7ba20e7a4a0e9 |
|||
title: '[FastAPI] Python製のASGI Web フレームワーク FastAPIに入門する' |
|||
- author: '@bee2' |
|||
author_link: https://qiita.com/bee2 |
|||
link: https://qiita.com/bee2/items/0ad260ab9835a2087dae |
|||
title: PythonのWeb frameworkのパフォーマンス比較 (Django, Flask, responder, FastAPI, japronto) |
|||
- author: ライトコードメディア編集部 |
|||
author_link: https://rightcode.co.jp/author/jun |
|||
link: https://rightcode.co.jp/blog/information-technology/fastapi-tutorial-todo-apps-admin-page-improvement |
|||
title: '【第4回】FastAPIチュートリアル: toDoアプリを作ってみよう【管理者ページ改良編】' |
|||
- author: ライトコードメディア編集部 |
|||
author_link: https://rightcode.co.jp/author/jun |
|||
link: https://rightcode.co.jp/blog/information-technology/fastapi-tutorial-todo-apps-authentication-user-registration |
|||
title: '【第3回】FastAPIチュートリアル: toDoアプリを作ってみよう【認証・ユーザ登録編】' |
|||
- author: ライトコードメディア編集部 |
|||
author_link: https://rightcode.co.jp/author/jun |
|||
link: https://rightcode.co.jp/blog/information-technology/fastapi-tutorial-todo-apps-model-building |
|||
title: '【第2回】FastAPIチュートリアル: ToDoアプリを作ってみよう【モデル構築編】' |
|||
- author: ライトコードメディア編集部 |
|||
author_link: https://rightcode.co.jp/author/jun |
|||
link: https://rightcode.co.jp/blog/information-technology/fastapi-tutorial-todo-apps-environment |
|||
title: '【第1回】FastAPIチュートリアル: ToDoアプリを作ってみよう【環境構築編】' |
|||
- author: Hikaru Takahashi |
|||
author_link: https://qiita.com/hikarut |
|||
link: https://qiita.com/hikarut/items/b178af2e2440c67c6ac4 |
|||
title: フロントエンド開発者向けのDockerによるPython開発環境構築 |
|||
- author: '@angel_katayoku' |
|||
author_link: https://qiita.com/angel_katayoku |
|||
link: https://qiita.com/angel_katayoku/items/8a458a8952f50b73f420 |
|||
title: FastAPIでPOSTされたJSONのレスポンスbodyを受け取る |
|||
- author: '@angel_katayoku' |
|||
author_link: https://qiita.com/angel_katayoku |
|||
link: https://qiita.com/angel_katayoku/items/4fbc1a4e2b33fa2237d2 |
|||
title: FastAPIをMySQLと接続してDockerで管理してみる |
|||
- author: '@angel_katayoku' |
|||
author_link: https://qiita.com/angel_katayoku |
|||
link: https://qiita.com/angel_katayoku/items/0e1f5dbbe62efc612a78 |
|||
title: FastAPIでCORSを回避 |
|||
- author: '@ryoryomaru' |
|||
author_link: https://qiita.com/ryoryomaru |
|||
link: https://qiita.com/ryoryomaru/items/59958ed385b3571d50de |
|||
title: python製の最新APIフレームワーク FastAPI を触ってみた |
|||
- author: '@mtitg' |
|||
author_link: https://qiita.com/mtitg |
|||
link: https://qiita.com/mtitg/items/47770e9a562dd150631d |
|||
title: FastAPI|DB接続してCRUDするPython製APIサーバーを構築 |
|||
Portuguese: |
|||
- author: Eduardo Mendes |
|||
author_link: https://bolha.us/@dunossauro |
|||
link: https://fastapidozero.dunossauro.com/ |
|||
title: FastAPI do ZERO |
|||
- author: Jessica Temporal |
|||
author_link: https://jtemporal.com/socials |
|||
link: https://jtemporal.com/dicas-para-migrar-de-flask-para-fastapi-e-vice-versa/ |
|||
title: Dicas para migrar uma aplicação de Flask para FastAPI e vice-versa |
|||
Russian: |
|||
- author: Troy Köhler |
|||
author_link: https://www.linkedin.com/in/trkohler/ |
|||
link: https://trkohler.com/fast-api-introduction-to-framework |
|||
title: 'FastAPI: знакомимся с фреймворком' |
|||
- author: prostomarkeloff |
|||
author_link: https://github.com/prostomarkeloff |
|||
link: https://habr.com/ru/post/478620/ |
|||
title: Почему Вы должны попробовать FastAPI? |
|||
- author: Andrey Korchak |
|||
author_link: https://habr.com/ru/users/57uff3r/ |
|||
link: https://habr.com/ru/post/454440/ |
|||
title: 'Мелкая питонячая радость #2: Starlette - Солидная примочка – FastAPI' |
|||
Vietnamese: |
|||
- author: Nguyễn Nhân |
|||
author_link: https://fullstackstation.com/author/figonking/ |
|||
link: https://fullstackstation.com/fastapi-trien-khai-bang-docker/ |
|||
title: 'FASTAPI: TRIỂN KHAI BẰNG DOCKER' |
|||
Taiwanese: |
|||
- author: Leon |
|||
author_link: http://editor.leonh.space/ |
|||
link: https://editor.leonh.space/2022/tortoise/ |
|||
title: 'Tortoise ORM / FastAPI 整合快速筆記' |
|||
Spanish: |
|||
- author: Eduardo Zepeda |
|||
author_link: https://coffeebytes.dev/en/authors/eduardo-zepeda/ |
|||
link: https://coffeebytes.dev/es/python-fastapi-el-mejor-framework-de-python/ |
|||
title: 'Tutorial de FastAPI, ¿el mejor framework de Python?' |
|||
Podcasts: |
|||
English: |
|||
- author: Behind the Commit |
|||
author_link: https://www.youtube.com/@BehindtheCommit |
|||
link: https://youtu.be/iaDRYUQ0OMM |
|||
title: Why FastAPI Became Python’s Fastest‑Growing Framework – Chat with Sebastián Ramírez |
|||
- author: Real Python |
|||
author_link: https://realpython.com/ |
|||
link: https://realpython.com/podcasts/rpp/72/ |
|||
title: Starting With FastAPI and Examining Python's Import System - Episode 72 |
|||
- author: Python Bytes FM |
|||
author_link: https://pythonbytes.fm/ |
|||
link: https://www.pythonpodcast.com/fastapi-web-application-framework-episode-259/ |
|||
title: 'Do you dare to press "."? - Episode 247 - Dan #6: SQLModel - use the same models for SQL and FastAPI' |
|||
- author: Podcast.`__init__` |
|||
author_link: https://www.pythonpodcast.com/ |
|||
link: https://www.pythonpodcast.com/fastapi-web-application-framework-episode-259/ |
|||
title: Build The Next Generation Of Python Web Applications With FastAPI - Episode 259 - interview to Sebastían Ramírez (tiangolo) |
|||
- author: Python Bytes FM |
|||
author_link: https://pythonbytes.fm/ |
|||
link: https://pythonbytes.fm/episodes/show/123/time-to-right-the-py-wrongs?time_in_sec=855 |
|||
title: FastAPI on PythonBytes |
|||
Talks: |
|||
English: |
|||
- author: Sebastián Ramírez (tiangolo) |
|||
author_link: https://x.com/tiangolo |
|||
link: https://www.youtube.com/watch?v=mwvmfl8nN_U |
|||
title: 'Keynote: Behind the scenes of FastAPI and friends for developers and builders — Sebastián Ramírez' |
|||
- author: Jeny Sadadia |
|||
author_link: https://github.com/JenySadadia |
|||
link: https://www.youtube.com/watch?v=uZdTe8_Z6BQ |
|||
title: 'PyCon AU 2023: Testing asynchronous applications with FastAPI and pytest' |
|||
- author: Sebastián Ramírez (tiangolo) |
|||
author_link: https://x.com/tiangolo |
|||
link: https://www.youtube.com/watch?v=PnpTY1f4k2U |
|||
title: '[VIRTUAL] Py.Amsterdam''s flying Software Circus: Intro to FastAPI' |
|||
- author: Sebastián Ramírez (tiangolo) |
|||
author_link: https://x.com/tiangolo |
|||
link: https://www.youtube.com/watch?v=z9K5pwb0rt8 |
|||
title: 'PyConBY 2020: Serve ML models easily with FastAPI' |
|||
- author: Chris Withers |
|||
author_link: https://x.com/chriswithers13 |
|||
link: https://www.youtube.com/watch?v=3DLwPcrE5mA |
|||
title: 'PyCon UK 2019: FastAPI from the ground up' |
|||
Taiwanese: |
|||
- author: Blueswen |
|||
author_link: https://github.com/blueswen |
|||
link: https://www.youtube.com/watch?v=y3sumuoDq4w |
|||
title: 'PyCon TW 2024: 全方位強化 Python 服務可觀測性:以 FastAPI 和 Grafana Stack 為例' |
|||
@ -1,3 +1,3 @@ |
|||
# Resources { #resources } |
|||
|
|||
Additional resources, external links, articles and more. ✈️ |
|||
Additional resources, external links, and more. ✈️ |
|||
|
|||
@ -0,0 +1,28 @@ |
|||
from fastapi import FastAPI |
|||
from fastapi.responses import FileResponse |
|||
from pydantic import BaseModel |
|||
|
|||
|
|||
class Item(BaseModel): |
|||
id: str |
|||
value: str |
|||
|
|||
|
|||
app = FastAPI() |
|||
|
|||
|
|||
@app.get( |
|||
"/items/{item_id}", |
|||
response_model=Item, |
|||
responses={ |
|||
200: { |
|||
"content": {"image/png": {}}, |
|||
"description": "Return the JSON item or an image.", |
|||
} |
|||
}, |
|||
) |
|||
async def read_item(item_id: str, img: bool | None = None): |
|||
if img: |
|||
return FileResponse("image.png", media_type="image/png") |
|||
else: |
|||
return {"id": "foo", "value": "there goes my hero"} |
|||
@ -0,0 +1,30 @@ |
|||
from fastapi import FastAPI |
|||
from fastapi.responses import FileResponse |
|||
from pydantic import BaseModel |
|||
|
|||
|
|||
class Item(BaseModel): |
|||
id: str |
|||
value: str |
|||
|
|||
|
|||
responses = { |
|||
404: {"description": "Item not found"}, |
|||
302: {"description": "The item was moved"}, |
|||
403: {"description": "Not enough privileges"}, |
|||
} |
|||
|
|||
|
|||
app = FastAPI() |
|||
|
|||
|
|||
@app.get( |
|||
"/items/{item_id}", |
|||
response_model=Item, |
|||
responses={**responses, 200: {"content": {"image/png": {}}}}, |
|||
) |
|||
async def read_item(item_id: str, img: bool | None = None): |
|||
if img: |
|||
return FileResponse("image.png", media_type="image/png") |
|||
else: |
|||
return {"id": "foo", "value": "there goes my hero"} |
|||
@ -0,0 +1,36 @@ |
|||
import gzip |
|||
from typing import Callable, List |
|||
|
|||
from fastapi import Body, FastAPI, Request, Response |
|||
from fastapi.routing import APIRoute |
|||
from typing_extensions import Annotated |
|||
|
|||
|
|||
class GzipRequest(Request): |
|||
async def body(self) -> bytes: |
|||
if not hasattr(self, "_body"): |
|||
body = await super().body() |
|||
if "gzip" in self.headers.getlist("Content-Encoding"): |
|||
body = gzip.decompress(body) |
|||
self._body = body |
|||
return self._body |
|||
|
|||
|
|||
class GzipRoute(APIRoute): |
|||
def get_route_handler(self) -> Callable: |
|||
original_route_handler = super().get_route_handler() |
|||
|
|||
async def custom_route_handler(request: Request) -> Response: |
|||
request = GzipRequest(request.scope, request.receive) |
|||
return await original_route_handler(request) |
|||
|
|||
return custom_route_handler |
|||
|
|||
|
|||
app = FastAPI() |
|||
app.router.route_class = GzipRoute |
|||
|
|||
|
|||
@app.post("/sum") |
|||
async def sum_numbers(numbers: Annotated[List[int], Body()]): |
|||
return {"sum": sum(numbers)} |
|||
@ -0,0 +1,36 @@ |
|||
import gzip |
|||
from collections.abc import Callable |
|||
from typing import Annotated |
|||
|
|||
from fastapi import Body, FastAPI, Request, Response |
|||
from fastapi.routing import APIRoute |
|||
|
|||
|
|||
class GzipRequest(Request): |
|||
async def body(self) -> bytes: |
|||
if not hasattr(self, "_body"): |
|||
body = await super().body() |
|||
if "gzip" in self.headers.getlist("Content-Encoding"): |
|||
body = gzip.decompress(body) |
|||
self._body = body |
|||
return self._body |
|||
|
|||
|
|||
class GzipRoute(APIRoute): |
|||
def get_route_handler(self) -> Callable: |
|||
original_route_handler = super().get_route_handler() |
|||
|
|||
async def custom_route_handler(request: Request) -> Response: |
|||
request = GzipRequest(request.scope, request.receive) |
|||
return await original_route_handler(request) |
|||
|
|||
return custom_route_handler |
|||
|
|||
|
|||
app = FastAPI() |
|||
app.router.route_class = GzipRoute |
|||
|
|||
|
|||
@app.post("/sum") |
|||
async def sum_numbers(numbers: Annotated[list[int], Body()]): |
|||
return {"sum": sum(numbers)} |
|||
@ -0,0 +1,35 @@ |
|||
import gzip |
|||
from typing import Annotated, Callable |
|||
|
|||
from fastapi import Body, FastAPI, Request, Response |
|||
from fastapi.routing import APIRoute |
|||
|
|||
|
|||
class GzipRequest(Request): |
|||
async def body(self) -> bytes: |
|||
if not hasattr(self, "_body"): |
|||
body = await super().body() |
|||
if "gzip" in self.headers.getlist("Content-Encoding"): |
|||
body = gzip.decompress(body) |
|||
self._body = body |
|||
return self._body |
|||
|
|||
|
|||
class GzipRoute(APIRoute): |
|||
def get_route_handler(self) -> Callable: |
|||
original_route_handler = super().get_route_handler() |
|||
|
|||
async def custom_route_handler(request: Request) -> Response: |
|||
request = GzipRequest(request.scope, request.receive) |
|||
return await original_route_handler(request) |
|||
|
|||
return custom_route_handler |
|||
|
|||
|
|||
app = FastAPI() |
|||
app.router.route_class = GzipRoute |
|||
|
|||
|
|||
@app.post("/sum") |
|||
async def sum_numbers(numbers: Annotated[list[int], Body()]): |
|||
return {"sum": sum(numbers)} |
|||
@ -0,0 +1,35 @@ |
|||
import gzip |
|||
from collections.abc import Callable |
|||
|
|||
from fastapi import Body, FastAPI, Request, Response |
|||
from fastapi.routing import APIRoute |
|||
|
|||
|
|||
class GzipRequest(Request): |
|||
async def body(self) -> bytes: |
|||
if not hasattr(self, "_body"): |
|||
body = await super().body() |
|||
if "gzip" in self.headers.getlist("Content-Encoding"): |
|||
body = gzip.decompress(body) |
|||
self._body = body |
|||
return self._body |
|||
|
|||
|
|||
class GzipRoute(APIRoute): |
|||
def get_route_handler(self) -> Callable: |
|||
original_route_handler = super().get_route_handler() |
|||
|
|||
async def custom_route_handler(request: Request) -> Response: |
|||
request = GzipRequest(request.scope, request.receive) |
|||
return await original_route_handler(request) |
|||
|
|||
return custom_route_handler |
|||
|
|||
|
|||
app = FastAPI() |
|||
app.router.route_class = GzipRoute |
|||
|
|||
|
|||
@app.post("/sum") |
|||
async def sum_numbers(numbers: list[int] = Body()): |
|||
return {"sum": sum(numbers)} |
|||
@ -0,0 +1,35 @@ |
|||
import gzip |
|||
from typing import Callable |
|||
|
|||
from fastapi import Body, FastAPI, Request, Response |
|||
from fastapi.routing import APIRoute |
|||
|
|||
|
|||
class GzipRequest(Request): |
|||
async def body(self) -> bytes: |
|||
if not hasattr(self, "_body"): |
|||
body = await super().body() |
|||
if "gzip" in self.headers.getlist("Content-Encoding"): |
|||
body = gzip.decompress(body) |
|||
self._body = body |
|||
return self._body |
|||
|
|||
|
|||
class GzipRoute(APIRoute): |
|||
def get_route_handler(self) -> Callable: |
|||
original_route_handler = super().get_route_handler() |
|||
|
|||
async def custom_route_handler(request: Request) -> Response: |
|||
request = GzipRequest(request.scope, request.receive) |
|||
return await original_route_handler(request) |
|||
|
|||
return custom_route_handler |
|||
|
|||
|
|||
app = FastAPI() |
|||
app.router.route_class = GzipRoute |
|||
|
|||
|
|||
@app.post("/sum") |
|||
async def sum_numbers(numbers: list[int] = Body()): |
|||
return {"sum": sum(numbers)} |
|||
@ -0,0 +1,30 @@ |
|||
from typing import Callable, List |
|||
|
|||
from fastapi import Body, FastAPI, HTTPException, Request, Response |
|||
from fastapi.exceptions import RequestValidationError |
|||
from fastapi.routing import APIRoute |
|||
from typing_extensions import Annotated |
|||
|
|||
|
|||
class ValidationErrorLoggingRoute(APIRoute): |
|||
def get_route_handler(self) -> Callable: |
|||
original_route_handler = super().get_route_handler() |
|||
|
|||
async def custom_route_handler(request: Request) -> Response: |
|||
try: |
|||
return await original_route_handler(request) |
|||
except RequestValidationError as exc: |
|||
body = await request.body() |
|||
detail = {"errors": exc.errors(), "body": body.decode()} |
|||
raise HTTPException(status_code=422, detail=detail) |
|||
|
|||
return custom_route_handler |
|||
|
|||
|
|||
app = FastAPI() |
|||
app.router.route_class = ValidationErrorLoggingRoute |
|||
|
|||
|
|||
@app.post("/") |
|||
async def sum_numbers(numbers: Annotated[List[int], Body()]): |
|||
return sum(numbers) |
|||
@ -0,0 +1,30 @@ |
|||
from collections.abc import Callable |
|||
from typing import Annotated |
|||
|
|||
from fastapi import Body, FastAPI, HTTPException, Request, Response |
|||
from fastapi.exceptions import RequestValidationError |
|||
from fastapi.routing import APIRoute |
|||
|
|||
|
|||
class ValidationErrorLoggingRoute(APIRoute): |
|||
def get_route_handler(self) -> Callable: |
|||
original_route_handler = super().get_route_handler() |
|||
|
|||
async def custom_route_handler(request: Request) -> Response: |
|||
try: |
|||
return await original_route_handler(request) |
|||
except RequestValidationError as exc: |
|||
body = await request.body() |
|||
detail = {"errors": exc.errors(), "body": body.decode()} |
|||
raise HTTPException(status_code=422, detail=detail) |
|||
|
|||
return custom_route_handler |
|||
|
|||
|
|||
app = FastAPI() |
|||
app.router.route_class = ValidationErrorLoggingRoute |
|||
|
|||
|
|||
@app.post("/") |
|||
async def sum_numbers(numbers: Annotated[list[int], Body()]): |
|||
return sum(numbers) |
|||
@ -0,0 +1,29 @@ |
|||
from typing import Annotated, Callable |
|||
|
|||
from fastapi import Body, FastAPI, HTTPException, Request, Response |
|||
from fastapi.exceptions import RequestValidationError |
|||
from fastapi.routing import APIRoute |
|||
|
|||
|
|||
class ValidationErrorLoggingRoute(APIRoute): |
|||
def get_route_handler(self) -> Callable: |
|||
original_route_handler = super().get_route_handler() |
|||
|
|||
async def custom_route_handler(request: Request) -> Response: |
|||
try: |
|||
return await original_route_handler(request) |
|||
except RequestValidationError as exc: |
|||
body = await request.body() |
|||
detail = {"errors": exc.errors(), "body": body.decode()} |
|||
raise HTTPException(status_code=422, detail=detail) |
|||
|
|||
return custom_route_handler |
|||
|
|||
|
|||
app = FastAPI() |
|||
app.router.route_class = ValidationErrorLoggingRoute |
|||
|
|||
|
|||
@app.post("/") |
|||
async def sum_numbers(numbers: Annotated[list[int], Body()]): |
|||
return sum(numbers) |
|||
@ -0,0 +1,29 @@ |
|||
from collections.abc import Callable |
|||
|
|||
from fastapi import Body, FastAPI, HTTPException, Request, Response |
|||
from fastapi.exceptions import RequestValidationError |
|||
from fastapi.routing import APIRoute |
|||
|
|||
|
|||
class ValidationErrorLoggingRoute(APIRoute): |
|||
def get_route_handler(self) -> Callable: |
|||
original_route_handler = super().get_route_handler() |
|||
|
|||
async def custom_route_handler(request: Request) -> Response: |
|||
try: |
|||
return await original_route_handler(request) |
|||
except RequestValidationError as exc: |
|||
body = await request.body() |
|||
detail = {"errors": exc.errors(), "body": body.decode()} |
|||
raise HTTPException(status_code=422, detail=detail) |
|||
|
|||
return custom_route_handler |
|||
|
|||
|
|||
app = FastAPI() |
|||
app.router.route_class = ValidationErrorLoggingRoute |
|||
|
|||
|
|||
@app.post("/") |
|||
async def sum_numbers(numbers: list[int] = Body()): |
|||
return sum(numbers) |
|||
@ -0,0 +1,29 @@ |
|||
from typing import Callable |
|||
|
|||
from fastapi import Body, FastAPI, HTTPException, Request, Response |
|||
from fastapi.exceptions import RequestValidationError |
|||
from fastapi.routing import APIRoute |
|||
|
|||
|
|||
class ValidationErrorLoggingRoute(APIRoute): |
|||
def get_route_handler(self) -> Callable: |
|||
original_route_handler = super().get_route_handler() |
|||
|
|||
async def custom_route_handler(request: Request) -> Response: |
|||
try: |
|||
return await original_route_handler(request) |
|||
except RequestValidationError as exc: |
|||
body = await request.body() |
|||
detail = {"errors": exc.errors(), "body": body.decode()} |
|||
raise HTTPException(status_code=422, detail=detail) |
|||
|
|||
return custom_route_handler |
|||
|
|||
|
|||
app = FastAPI() |
|||
app.router.route_class = ValidationErrorLoggingRoute |
|||
|
|||
|
|||
@app.post("/") |
|||
async def sum_numbers(numbers: list[int] = Body()): |
|||
return sum(numbers) |
|||
@ -0,0 +1,39 @@ |
|||
import time |
|||
from collections.abc import Callable |
|||
|
|||
from fastapi import APIRouter, FastAPI, Request, Response |
|||
from fastapi.routing import APIRoute |
|||
|
|||
|
|||
class TimedRoute(APIRoute): |
|||
def get_route_handler(self) -> Callable: |
|||
original_route_handler = super().get_route_handler() |
|||
|
|||
async def custom_route_handler(request: Request) -> Response: |
|||
before = time.time() |
|||
response: Response = await original_route_handler(request) |
|||
duration = time.time() - before |
|||
response.headers["X-Response-Time"] = str(duration) |
|||
print(f"route duration: {duration}") |
|||
print(f"route response: {response}") |
|||
print(f"route response headers: {response.headers}") |
|||
return response |
|||
|
|||
return custom_route_handler |
|||
|
|||
|
|||
app = FastAPI() |
|||
router = APIRouter(route_class=TimedRoute) |
|||
|
|||
|
|||
@app.get("/") |
|||
async def not_timed(): |
|||
return {"message": "Not timed"} |
|||
|
|||
|
|||
@router.get("/timed") |
|||
async def timed(): |
|||
return {"message": "It's the time of my life"} |
|||
|
|||
|
|||
app.include_router(router) |
|||
@ -0,0 +1,19 @@ |
|||
from dataclasses import dataclass |
|||
|
|||
from fastapi import FastAPI |
|||
|
|||
|
|||
@dataclass |
|||
class Item: |
|||
name: str |
|||
price: float |
|||
description: str | None = None |
|||
tax: float | None = None |
|||
|
|||
|
|||
app = FastAPI() |
|||
|
|||
|
|||
@app.post("/items/") |
|||
async def create_item(item: Item): |
|||
return item |
|||
@ -0,0 +1,25 @@ |
|||
from dataclasses import dataclass, field |
|||
|
|||
from fastapi import FastAPI |
|||
|
|||
|
|||
@dataclass |
|||
class Item: |
|||
name: str |
|||
price: float |
|||
tags: list[str] = field(default_factory=list) |
|||
description: str | None = None |
|||
tax: float | None = None |
|||
|
|||
|
|||
app = FastAPI() |
|||
|
|||
|
|||
@app.get("/items/next", response_model=Item) |
|||
async def read_next_item(): |
|||
return { |
|||
"name": "Island In The Moon", |
|||
"price": 12.99, |
|||
"description": "A place to be playin' and havin' fun", |
|||
"tags": ["breater"], |
|||
} |
|||
@ -0,0 +1,26 @@ |
|||
from dataclasses import dataclass, field |
|||
from typing import Union |
|||
|
|||
from fastapi import FastAPI |
|||
|
|||
|
|||
@dataclass |
|||
class Item: |
|||
name: str |
|||
price: float |
|||
tags: list[str] = field(default_factory=list) |
|||
description: Union[str, None] = None |
|||
tax: Union[float, None] = None |
|||
|
|||
|
|||
app = FastAPI() |
|||
|
|||
|
|||
@app.get("/items/next", response_model=Item) |
|||
async def read_next_item(): |
|||
return { |
|||
"name": "Island In The Moon", |
|||
"price": 12.99, |
|||
"description": "A place to be playin' and havin' fun", |
|||
"tags": ["breater"], |
|||
} |
|||
@ -0,0 +1,54 @@ |
|||
from dataclasses import field # (1) |
|||
|
|||
from fastapi import FastAPI |
|||
from pydantic.dataclasses import dataclass # (2) |
|||
|
|||
|
|||
@dataclass |
|||
class Item: |
|||
name: str |
|||
description: str | None = None |
|||
|
|||
|
|||
@dataclass |
|||
class Author: |
|||
name: str |
|||
items: list[Item] = field(default_factory=list) # (3) |
|||
|
|||
|
|||
app = FastAPI() |
|||
|
|||
|
|||
@app.post("/authors/{author_id}/items/", response_model=Author) # (4) |
|||
async def create_author_items(author_id: str, items: list[Item]): # (5) |
|||
return {"name": author_id, "items": items} # (6) |
|||
|
|||
|
|||
@app.get("/authors/", response_model=list[Author]) # (7) |
|||
def get_authors(): # (8) |
|||
return [ # (9) |
|||
{ |
|||
"name": "Breaters", |
|||
"items": [ |
|||
{ |
|||
"name": "Island In The Moon", |
|||
"description": "A place to be playin' and havin' fun", |
|||
}, |
|||
{"name": "Holy Buddies"}, |
|||
], |
|||
}, |
|||
{ |
|||
"name": "System of an Up", |
|||
"items": [ |
|||
{ |
|||
"name": "Salt", |
|||
"description": "The kombucha mushroom people's favorite", |
|||
}, |
|||
{"name": "Pad Thai"}, |
|||
{ |
|||
"name": "Lonely Night", |
|||
"description": "The mostests lonliest nightiest of allest", |
|||
}, |
|||
], |
|||
}, |
|||
] |
|||
@ -0,0 +1,55 @@ |
|||
from dataclasses import field # (1) |
|||
from typing import Union |
|||
|
|||
from fastapi import FastAPI |
|||
from pydantic.dataclasses import dataclass # (2) |
|||
|
|||
|
|||
@dataclass |
|||
class Item: |
|||
name: str |
|||
description: Union[str, None] = None |
|||
|
|||
|
|||
@dataclass |
|||
class Author: |
|||
name: str |
|||
items: list[Item] = field(default_factory=list) # (3) |
|||
|
|||
|
|||
app = FastAPI() |
|||
|
|||
|
|||
@app.post("/authors/{author_id}/items/", response_model=Author) # (4) |
|||
async def create_author_items(author_id: str, items: list[Item]): # (5) |
|||
return {"name": author_id, "items": items} # (6) |
|||
|
|||
|
|||
@app.get("/authors/", response_model=list[Author]) # (7) |
|||
def get_authors(): # (8) |
|||
return [ # (9) |
|||
{ |
|||
"name": "Breaters", |
|||
"items": [ |
|||
{ |
|||
"name": "Island In The Moon", |
|||
"description": "A place to be playin' and havin' fun", |
|||
}, |
|||
{"name": "Holy Buddies"}, |
|||
], |
|||
}, |
|||
{ |
|||
"name": "System of an Up", |
|||
"items": [ |
|||
{ |
|||
"name": "Salt", |
|||
"description": "The kombucha mushroom people's favorite", |
|||
}, |
|||
{"name": "Pad Thai"}, |
|||
{ |
|||
"name": "Lonely Night", |
|||
"description": "The mostests lonliest nightiest of allest", |
|||
}, |
|||
], |
|||
}, |
|||
] |
|||
@ -0,0 +1,51 @@ |
|||
from fastapi import APIRouter, FastAPI |
|||
from pydantic import BaseModel, HttpUrl |
|||
|
|||
app = FastAPI() |
|||
|
|||
|
|||
class Invoice(BaseModel): |
|||
id: str |
|||
title: str | None = None |
|||
customer: str |
|||
total: float |
|||
|
|||
|
|||
class InvoiceEvent(BaseModel): |
|||
description: str |
|||
paid: bool |
|||
|
|||
|
|||
class InvoiceEventReceived(BaseModel): |
|||
ok: bool |
|||
|
|||
|
|||
invoices_callback_router = APIRouter() |
|||
|
|||
|
|||
@invoices_callback_router.post( |
|||
"{$callback_url}/invoices/{$request.body.id}", response_model=InvoiceEventReceived |
|||
) |
|||
def invoice_notification(body: InvoiceEvent): |
|||
pass |
|||
|
|||
|
|||
@app.post("/invoices/", callbacks=invoices_callback_router.routes) |
|||
def create_invoice(invoice: Invoice, callback_url: HttpUrl | None = None): |
|||
""" |
|||
Create an invoice. |
|||
|
|||
This will (let's imagine) let the API user (some external developer) create an |
|||
invoice. |
|||
|
|||
And this path operation will: |
|||
|
|||
* Send the invoice to the client. |
|||
* Collect the money from the client. |
|||
* Send a notification back to the API user (the external developer), as a callback. |
|||
* At this point is that the API will somehow send a POST request to the |
|||
external API with the notification of the invoice event |
|||
(e.g. "payment successful"). |
|||
""" |
|||
# Send the invoice, collect the money, send the notification (the callback) |
|||
return {"msg": "Invoice received"} |
|||
@ -0,0 +1,28 @@ |
|||
from fastapi import FastAPI |
|||
from pydantic import BaseModel |
|||
|
|||
app = FastAPI() |
|||
|
|||
|
|||
class Item(BaseModel): |
|||
name: str |
|||
description: str | None = None |
|||
price: float |
|||
tax: float | None = None |
|||
tags: set[str] = set() |
|||
|
|||
|
|||
@app.post("/items/", response_model=Item, summary="Create an item") |
|||
async def create_item(item: Item): |
|||
""" |
|||
Create an item with all the information: |
|||
|
|||
- **name**: each item must have a name |
|||
- **description**: a long description |
|||
- **price**: required |
|||
- **tax**: if the item doesn't have tax, you can omit this |
|||
- **tags**: a set of unique tag strings for this item |
|||
\f |
|||
:param item: User input. |
|||
""" |
|||
return item |
|||
@ -0,0 +1,30 @@ |
|||
from typing import Union |
|||
|
|||
from fastapi import FastAPI |
|||
from pydantic import BaseModel |
|||
|
|||
app = FastAPI() |
|||
|
|||
|
|||
class Item(BaseModel): |
|||
name: str |
|||
description: Union[str, None] = None |
|||
price: float |
|||
tax: Union[float, None] = None |
|||
tags: set[str] = set() |
|||
|
|||
|
|||
@app.post("/items/", response_model=Item, summary="Create an item") |
|||
async def create_item(item: Item): |
|||
""" |
|||
Create an item with all the information: |
|||
|
|||
- **name**: each item must have a name |
|||
- **description**: a long description |
|||
- **price**: required |
|||
- **tax**: if the item doesn't have tax, you can omit this |
|||
- **tags**: a set of unique tag strings for this item |
|||
\f |
|||
:param item: User input. |
|||
""" |
|||
return item |
|||
@ -0,0 +1,32 @@ |
|||
import yaml |
|||
from fastapi import FastAPI, HTTPException, Request |
|||
from pydantic import BaseModel, ValidationError |
|||
|
|||
app = FastAPI() |
|||
|
|||
|
|||
class Item(BaseModel): |
|||
name: str |
|||
tags: list[str] |
|||
|
|||
|
|||
@app.post( |
|||
"/items/", |
|||
openapi_extra={ |
|||
"requestBody": { |
|||
"content": {"application/x-yaml": {"schema": Item.schema()}}, |
|||
"required": True, |
|||
}, |
|||
}, |
|||
) |
|||
async def create_item(request: Request): |
|||
raw_body = await request.body() |
|||
try: |
|||
data = yaml.safe_load(raw_body) |
|||
except yaml.YAMLError: |
|||
raise HTTPException(status_code=422, detail="Invalid YAML") |
|||
try: |
|||
item = Item.parse_obj(data) |
|||
except ValidationError as e: |
|||
raise HTTPException(status_code=422, detail=e.errors()) |
|||
return item |
|||
@ -0,0 +1,32 @@ |
|||
import yaml |
|||
from fastapi import FastAPI, HTTPException, Request |
|||
from pydantic import BaseModel, ValidationError |
|||
|
|||
app = FastAPI() |
|||
|
|||
|
|||
class Item(BaseModel): |
|||
name: str |
|||
tags: list[str] |
|||
|
|||
|
|||
@app.post( |
|||
"/items/", |
|||
openapi_extra={ |
|||
"requestBody": { |
|||
"content": {"application/x-yaml": {"schema": Item.model_json_schema()}}, |
|||
"required": True, |
|||
}, |
|||
}, |
|||
) |
|||
async def create_item(request: Request): |
|||
raw_body = await request.body() |
|||
try: |
|||
data = yaml.safe_load(raw_body) |
|||
except yaml.YAMLError: |
|||
raise HTTPException(status_code=422, detail="Invalid YAML") |
|||
try: |
|||
item = Item.model_validate(data) |
|||
except ValidationError as e: |
|||
raise HTTPException(status_code=422, detail=e.errors(include_url=False)) |
|||
return item |
|||
@ -0,0 +1,21 @@ |
|||
from datetime import datetime |
|||
|
|||
from fastapi import FastAPI |
|||
from fastapi.encoders import jsonable_encoder |
|||
from fastapi.responses import JSONResponse |
|||
from pydantic import BaseModel |
|||
|
|||
|
|||
class Item(BaseModel): |
|||
title: str |
|||
timestamp: datetime |
|||
description: str | None = None |
|||
|
|||
|
|||
app = FastAPI() |
|||
|
|||
|
|||
@app.put("/items/{id}") |
|||
def update_item(id: str, item: Item): |
|||
json_compatible_item_data = jsonable_encoder(item) |
|||
return JSONResponse(content=json_compatible_item_data) |
|||
@ -0,0 +1,10 @@ |
|||
from pydantic import BaseSettings |
|||
|
|||
|
|||
class Settings(BaseSettings): |
|||
app_name: str = "Awesome API" |
|||
admin_email: str |
|||
items_per_user: int = 50 |
|||
|
|||
class Config: |
|||
env_file = ".env" |
|||
@ -0,0 +1,10 @@ |
|||
from pydantic import BaseSettings |
|||
|
|||
|
|||
class Settings(BaseSettings): |
|||
app_name: str = "Awesome API" |
|||
admin_email: str |
|||
items_per_user: int = 50 |
|||
|
|||
class Config: |
|||
env_file = ".env" |
|||
@ -0,0 +1,9 @@ |
|||
from pydantic import BaseModel |
|||
|
|||
|
|||
def forwardref_method(input: "ForwardRefModel") -> "ForwardRefModel": |
|||
return ForwardRefModel(x=input.x + 1) |
|||
|
|||
|
|||
class ForwardRefModel(BaseModel): |
|||
x: int = 0 |
|||
@ -0,0 +1,141 @@ |
|||
from typing import List |
|||
|
|||
import pytest |
|||
from fastapi import FastAPI |
|||
from fastapi.testclient import TestClient |
|||
from inline_snapshot import snapshot |
|||
from typing_extensions import Annotated |
|||
|
|||
from .utils import needs_pydanticv2 |
|||
|
|||
|
|||
@pytest.fixture(name="client") |
|||
def get_client(): |
|||
from pydantic import ( |
|||
BaseModel, |
|||
ConfigDict, |
|||
PlainSerializer, |
|||
TypeAdapter, |
|||
WithJsonSchema, |
|||
) |
|||
|
|||
class FakeNumpyArray: |
|||
def __init__(self): |
|||
self.data = [1.0, 2.0, 3.0] |
|||
|
|||
FakeNumpyArrayPydantic = Annotated[ |
|||
FakeNumpyArray, |
|||
WithJsonSchema(TypeAdapter(List[float]).json_schema()), |
|||
PlainSerializer(lambda v: v.data), |
|||
] |
|||
|
|||
class MyModel(BaseModel): |
|||
model_config = ConfigDict(arbitrary_types_allowed=True) |
|||
custom_field: FakeNumpyArrayPydantic |
|||
|
|||
app = FastAPI() |
|||
|
|||
@app.get("/") |
|||
def test() -> MyModel: |
|||
return MyModel(custom_field=FakeNumpyArray()) |
|||
|
|||
client = TestClient(app) |
|||
return client |
|||
|
|||
|
|||
@needs_pydanticv2 |
|||
def test_get(client: TestClient): |
|||
response = client.get("/") |
|||
assert response.json() == {"custom_field": [1.0, 2.0, 3.0]} |
|||
|
|||
|
|||
@needs_pydanticv2 |
|||
def test_typeadapter(): |
|||
# This test is only to confirm that Pydantic alone is working as expected |
|||
from pydantic import ( |
|||
BaseModel, |
|||
ConfigDict, |
|||
PlainSerializer, |
|||
TypeAdapter, |
|||
WithJsonSchema, |
|||
) |
|||
|
|||
class FakeNumpyArray: |
|||
def __init__(self): |
|||
self.data = [1.0, 2.0, 3.0] |
|||
|
|||
FakeNumpyArrayPydantic = Annotated[ |
|||
FakeNumpyArray, |
|||
WithJsonSchema(TypeAdapter(List[float]).json_schema()), |
|||
PlainSerializer(lambda v: v.data), |
|||
] |
|||
|
|||
class MyModel(BaseModel): |
|||
model_config = ConfigDict(arbitrary_types_allowed=True) |
|||
custom_field: FakeNumpyArrayPydantic |
|||
|
|||
ta = TypeAdapter(MyModel) |
|||
assert ta.dump_python(MyModel(custom_field=FakeNumpyArray())) == { |
|||
"custom_field": [1.0, 2.0, 3.0] |
|||
} |
|||
assert ta.json_schema() == snapshot( |
|||
{ |
|||
"properties": { |
|||
"custom_field": { |
|||
"items": {"type": "number"}, |
|||
"title": "Custom Field", |
|||
"type": "array", |
|||
} |
|||
}, |
|||
"required": ["custom_field"], |
|||
"title": "MyModel", |
|||
"type": "object", |
|||
} |
|||
) |
|||
|
|||
|
|||
@needs_pydanticv2 |
|||
def test_openapi_schema(client: TestClient): |
|||
response = client.get("openapi.json") |
|||
assert response.json() == snapshot( |
|||
{ |
|||
"openapi": "3.1.0", |
|||
"info": {"title": "FastAPI", "version": "0.1.0"}, |
|||
"paths": { |
|||
"/": { |
|||
"get": { |
|||
"summary": "Test", |
|||
"operationId": "test__get", |
|||
"responses": { |
|||
"200": { |
|||
"description": "Successful Response", |
|||
"content": { |
|||
"application/json": { |
|||
"schema": { |
|||
"$ref": "#/components/schemas/MyModel" |
|||
} |
|||
} |
|||
}, |
|||
} |
|||
}, |
|||
} |
|||
} |
|||
}, |
|||
"components": { |
|||
"schemas": { |
|||
"MyModel": { |
|||
"properties": { |
|||
"custom_field": { |
|||
"items": {"type": "number"}, |
|||
"type": "array", |
|||
"title": "Custom Field", |
|||
} |
|||
}, |
|||
"type": "object", |
|||
"required": ["custom_field"], |
|||
"title": "MyModel", |
|||
} |
|||
} |
|||
}, |
|||
} |
|||
) |
|||
@ -0,0 +1,251 @@ |
|||
from functools import partial |
|||
from typing import AsyncGenerator, Generator |
|||
|
|||
import pytest |
|||
from fastapi import Depends, FastAPI |
|||
from fastapi.testclient import TestClient |
|||
from typing_extensions import Annotated |
|||
|
|||
app = FastAPI() |
|||
|
|||
|
|||
def function_dependency(value: str) -> str: |
|||
return value |
|||
|
|||
|
|||
async def async_function_dependency(value: str) -> str: |
|||
return value |
|||
|
|||
|
|||
def gen_dependency(value: str) -> Generator[str, None, None]: |
|||
yield value |
|||
|
|||
|
|||
async def async_gen_dependency(value: str) -> AsyncGenerator[str, None]: |
|||
yield value |
|||
|
|||
|
|||
class CallableDependency: |
|||
def __call__(self, value: str) -> str: |
|||
return value |
|||
|
|||
|
|||
class CallableGenDependency: |
|||
def __call__(self, value: str) -> Generator[str, None, None]: |
|||
yield value |
|||
|
|||
|
|||
class AsyncCallableDependency: |
|||
async def __call__(self, value: str) -> str: |
|||
return value |
|||
|
|||
|
|||
class AsyncCallableGenDependency: |
|||
async def __call__(self, value: str) -> AsyncGenerator[str, None]: |
|||
yield value |
|||
|
|||
|
|||
class MethodsDependency: |
|||
def synchronous(self, value: str) -> str: |
|||
return value |
|||
|
|||
async def asynchronous(self, value: str) -> str: |
|||
return value |
|||
|
|||
def synchronous_gen(self, value: str) -> Generator[str, None, None]: |
|||
yield value |
|||
|
|||
async def asynchronous_gen(self, value: str) -> AsyncGenerator[str, None]: |
|||
yield value |
|||
|
|||
|
|||
callable_dependency = CallableDependency() |
|||
callable_gen_dependency = CallableGenDependency() |
|||
async_callable_dependency = AsyncCallableDependency() |
|||
async_callable_gen_dependency = AsyncCallableGenDependency() |
|||
methods_dependency = MethodsDependency() |
|||
|
|||
|
|||
@app.get("/partial-function-dependency") |
|||
async def get_partial_function_dependency( |
|||
value: Annotated[ |
|||
str, Depends(partial(function_dependency, "partial-function-dependency")) |
|||
], |
|||
) -> str: |
|||
return value |
|||
|
|||
|
|||
@app.get("/partial-async-function-dependency") |
|||
async def get_partial_async_function_dependency( |
|||
value: Annotated[ |
|||
str, |
|||
Depends( |
|||
partial(async_function_dependency, "partial-async-function-dependency") |
|||
), |
|||
], |
|||
) -> str: |
|||
return value |
|||
|
|||
|
|||
@app.get("/partial-gen-dependency") |
|||
async def get_partial_gen_dependency( |
|||
value: Annotated[str, Depends(partial(gen_dependency, "partial-gen-dependency"))], |
|||
) -> str: |
|||
return value |
|||
|
|||
|
|||
@app.get("/partial-async-gen-dependency") |
|||
async def get_partial_async_gen_dependency( |
|||
value: Annotated[ |
|||
str, Depends(partial(async_gen_dependency, "partial-async-gen-dependency")) |
|||
], |
|||
) -> str: |
|||
return value |
|||
|
|||
|
|||
@app.get("/partial-callable-dependency") |
|||
async def get_partial_callable_dependency( |
|||
value: Annotated[ |
|||
str, Depends(partial(callable_dependency, "partial-callable-dependency")) |
|||
], |
|||
) -> str: |
|||
return value |
|||
|
|||
|
|||
@app.get("/partial-callable-gen-dependency") |
|||
async def get_partial_callable_gen_dependency( |
|||
value: Annotated[ |
|||
str, |
|||
Depends(partial(callable_gen_dependency, "partial-callable-gen-dependency")), |
|||
], |
|||
) -> str: |
|||
return value |
|||
|
|||
|
|||
@app.get("/partial-async-callable-dependency") |
|||
async def get_partial_async_callable_dependency( |
|||
value: Annotated[ |
|||
str, |
|||
Depends( |
|||
partial(async_callable_dependency, "partial-async-callable-dependency") |
|||
), |
|||
], |
|||
) -> str: |
|||
return value |
|||
|
|||
|
|||
@app.get("/partial-async-callable-gen-dependency") |
|||
async def get_partial_async_callable_gen_dependency( |
|||
value: Annotated[ |
|||
str, |
|||
Depends( |
|||
partial( |
|||
async_callable_gen_dependency, "partial-async-callable-gen-dependency" |
|||
) |
|||
), |
|||
], |
|||
) -> str: |
|||
return value |
|||
|
|||
|
|||
@app.get("/partial-synchronous-method-dependency") |
|||
async def get_partial_synchronous_method_dependency( |
|||
value: Annotated[ |
|||
str, |
|||
Depends( |
|||
partial( |
|||
methods_dependency.synchronous, "partial-synchronous-method-dependency" |
|||
) |
|||
), |
|||
], |
|||
) -> str: |
|||
return value |
|||
|
|||
|
|||
@app.get("/partial-synchronous-method-gen-dependency") |
|||
async def get_partial_synchronous_method_gen_dependency( |
|||
value: Annotated[ |
|||
str, |
|||
Depends( |
|||
partial( |
|||
methods_dependency.synchronous_gen, |
|||
"partial-synchronous-method-gen-dependency", |
|||
) |
|||
), |
|||
], |
|||
) -> str: |
|||
return value |
|||
|
|||
|
|||
@app.get("/partial-asynchronous-method-dependency") |
|||
async def get_partial_asynchronous_method_dependency( |
|||
value: Annotated[ |
|||
str, |
|||
Depends( |
|||
partial( |
|||
methods_dependency.asynchronous, |
|||
"partial-asynchronous-method-dependency", |
|||
) |
|||
), |
|||
], |
|||
) -> str: |
|||
return value |
|||
|
|||
|
|||
@app.get("/partial-asynchronous-method-gen-dependency") |
|||
async def get_partial_asynchronous_method_gen_dependency( |
|||
value: Annotated[ |
|||
str, |
|||
Depends( |
|||
partial( |
|||
methods_dependency.asynchronous_gen, |
|||
"partial-asynchronous-method-gen-dependency", |
|||
) |
|||
), |
|||
], |
|||
) -> str: |
|||
return value |
|||
|
|||
|
|||
client = TestClient(app) |
|||
|
|||
|
|||
@pytest.mark.parametrize( |
|||
"route,value", |
|||
[ |
|||
("/partial-function-dependency", "partial-function-dependency"), |
|||
( |
|||
"/partial-async-function-dependency", |
|||
"partial-async-function-dependency", |
|||
), |
|||
("/partial-gen-dependency", "partial-gen-dependency"), |
|||
("/partial-async-gen-dependency", "partial-async-gen-dependency"), |
|||
("/partial-callable-dependency", "partial-callable-dependency"), |
|||
("/partial-callable-gen-dependency", "partial-callable-gen-dependency"), |
|||
("/partial-async-callable-dependency", "partial-async-callable-dependency"), |
|||
( |
|||
"/partial-async-callable-gen-dependency", |
|||
"partial-async-callable-gen-dependency", |
|||
), |
|||
( |
|||
"/partial-synchronous-method-dependency", |
|||
"partial-synchronous-method-dependency", |
|||
), |
|||
( |
|||
"/partial-synchronous-method-gen-dependency", |
|||
"partial-synchronous-method-gen-dependency", |
|||
), |
|||
( |
|||
"/partial-asynchronous-method-dependency", |
|||
"partial-asynchronous-method-dependency", |
|||
), |
|||
( |
|||
"/partial-asynchronous-method-gen-dependency", |
|||
"partial-asynchronous-method-gen-dependency", |
|||
), |
|||
], |
|||
) |
|||
def test_dependency_types_with_partial(route: str, value: str) -> None: |
|||
response = client.get(route) |
|||
assert response.status_code == 200, response.text |
|||
assert response.json() == value |
|||
Some files were not shown because too many files changed in this diff
Loading…
Reference in new issue