-
Notifications
You must be signed in to change notification settings - Fork 0
Expand file tree
/
Copy pathchunks.json
More file actions
92 lines (92 loc) · 55.5 KB
/
Copy pathchunks.json
File metadata and controls
92 lines (92 loc) · 55.5 KB
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
[
{
"id": "dependencies.txt-0",
"source": "dependencies.txt",
"text": "Dependencies \u00b6 FastAPI has a very powerful but intuitive Dependency Injection system. It is designed to be very simple to use, and to make it very easy for any developer to integrate other components with FastAPI . What is \"Dependency Injection\" \u00b6 \"Dependency Injection\" means, in programming, that there is a way for your code (in this case, your path operation functions ) to declare things that it requires to work and use: \"dependencies\". And then, that system (in this case FastAPI ) will take care of doing whatever is needed to provide your code with those needed dependencies (\"inject\" the dependencies). This is very useful when you need to: Have shared logic (the same code logic again and again). Share database connections. Enforce security, authentication, role requirements, etc. And many other things... All these, while minimizing code repetition. First Steps \u00b6 Let's see a very simple example. It will be so simple that it is not very useful, for now. But this way we can focus on how the Dependency Injection system works. Create a dependency, or \"dependable\" \u00b6 Let's first focus on the dependency. It is just a function that can take all the same parameters that a path operation function can take: Python 3.10+ from typing import Annotated from fastapi import Depends , FastAPI app = FastAPI () async def common_parameters ( q : str | None = None , skip : int = 0 , limit : int = 100 ): return { \"q\" : q , \"skip\" : skip , \"limit\" : limit } @app . get ( \"/items/\" ) async def read_items ( commons : Annotated [ dict , Depends ( common_parameters )]): return commons @app . get ( \"/users/\" ) async def read_users ( commons : Annotated [ dict , Depends ( common_parameters )]): return commons \ud83e\udd13 Other versions and variants Python 3.10+ - non-Annotated Tip Prefer to use the Annotated version if possible. from fastapi import Depends , FastAPI app = FastAPI () async def common_parameters ( q : str | None = None , skip : int = 0 , limit : int = 100 ): return { \"q\" : q , \"skip\" : skip , \"limit\" : limit } @app . get ( \"/items/\" ) async def read_items ( commons : dict = Depends ( common_parameters )): return commons @app . get ( \"/users/\" ) async def read_users ( commons : dict = Depends ( common_parameters )): return commons That's it. 2 lines . And it has the same shape and structure that all your path operation functions have. You can think of it as a path operation function without the \"decorator\" (without the @app.get(\"/some-path\") ). And it can return anything you want. In this case, this dependency expects: An optional query parameter q that is a str . An optional query parameter skip that is an int , and by default is 0 . An optional query parameter limit that is an int , and by default is 100 . And then it just returns a dict containing those values. Note FastAPI added support for Annotated (and started recommending it) in version 0.95.0. If you have an older version, you would get errors when trying to use Annotated . Make sure you Upgrade the FastAPI version to at least 0.95.1 before using Annotated . Import Depends \u00b6 Python 3.10+ from typing import Annotated from fastapi import Depends , FastAPI app = FastAPI () async def common_parameters ( q : str | None = None , skip : int = 0 , limit : int = 100 ): return {"
},
{
"id": "dependencies.txt-1",
"source": "dependencies.txt",
"text": ". And then it just returns a dict containing those values. Note FastAPI added support for Annotated (and started recommending it) in version 0.95.0. If you have an older version, you would get errors when trying to use Annotated . Make sure you Upgrade the FastAPI version to at least 0.95.1 before using Annotated . Import Depends \u00b6 Python 3.10+ from typing import Annotated from fastapi import Depends , FastAPI app = FastAPI () async def common_parameters ( q : str | None = None , skip : int = 0 , limit : int = 100 ): return { \"q\" : q , \"skip\" : skip , \"limit\" : limit } @app . get ( \"/items/\" ) async def read_items ( commons : Annotated [ dict , Depends ( common_parameters )]): return commons @app . get ( \"/users/\" ) async def read_users ( commons : Annotated [ dict , Depends ( common_parameters )]): return commons \ud83e\udd13 Other versions and variants Python 3.10+ - non-Annotated Tip Prefer to use the Annotated version if possible. from fastapi import Depends , FastAPI app = FastAPI () async def common_parameters ( q : str | None = None , skip : int = 0 , limit : int = 100 ): return { \"q\" : q , \"skip\" : skip , \"limit\" : limit } @app . get ( \"/items/\" ) async def read_items ( commons : dict = Depends ( common_parameters )): return commons @app . get ( \"/users/\" ) async def read_users ( commons : dict = Depends ( common_parameters )): return commons Declare the dependency, in the \"dependant\" \u00b6 The same way you use Body , Query , etc. with your path operation function parameters, use Depends with a new parameter: Python 3.10+ from typing import Annotated from fastapi import Depends , FastAPI app = FastAPI () async def common_parameters ( q : str | None = None , skip : int = 0 , limit : int = 100 ): return { \"q\" : q , \"skip\" : skip , \"limit\" : limit } @app . get ( \"/items/\" ) async def read_items ( commons : Annotated [ dict , Depends ( common_parameters )]): return commons @app . get ( \"/users/\" ) async def read_users ( commons : Annotated [ dict , Depends ( common_parameters )]): return commons \ud83e\udd13 Other versions and variants Python 3.10+ - non-Annotated Tip Prefer to use the Annotated version if possible. from fastapi import Depends , FastAPI app = FastAPI () async def common_parameters ( q : str | None = None , skip : int = 0 , limit : int = 100 ): return { \"q\" : q , \"skip\" : skip , \"limit\" : limit } @app . get ( \"/items/\" ) async def read_items ( commons : dict = Depends ( common_parameters )): return commons @app . get ( \"/users/\" ) async def read_users ( commons : dict = Depends ( common_parameters )): return commons Although you use Depends in the parameters of your function the same way you use Body , Query , etc, Depends works a bit differently. You only give Depends a single parameter. This parameter must be something like a function. You don't call it directly (don't add the parenthesis at the end), you just pass it as a parameter to Depends() . And that function takes parameters in the same way that path operation functions do. Tip You'll see what other \"things\", apart from functions, can be used as dependencies in the next chapter. Whenever a new request arrives, FastAPI will take care of: Calling"
},
{
"id": "dependencies.txt-2",
"source": "dependencies.txt",
"text": "the parameters of your function the same way you use Body , Query , etc, Depends works a bit differently. You only give Depends a single parameter. This parameter must be something like a function. You don't call it directly (don't add the parenthesis at the end), you just pass it as a parameter to Depends() . And that function takes parameters in the same way that path operation functions do. Tip You'll see what other \"things\", apart from functions, can be used as dependencies in the next chapter. Whenever a new request arrives, FastAPI will take care of: Calling your dependency (\"dependable\") function with the correct parameters. Get the result from your function. Assign that result to the parameter in your path operation function . graph TB common_parameters([\"common_parameters\"]) read_items[\"/items/\"] read_users[\"/users/\"] common_parameters --> read_items common_parameters --> read_users This way you write shared code once and FastAPI takes care of calling it for your path operations . Tip Notice that you don't have to create a special class and pass it somewhere to FastAPI to \"register\" it or anything similar. You just pass it to Depends and FastAPI knows how to do the rest. Share Annotated dependencies \u00b6 In the examples above, you see that there's a tiny bit of code duplication . When you need to use the common_parameters() dependency, you have to write the whole parameter with the type annotation and Depends() : commons : Annotated [ dict , Depends ( common_parameters )] But because we are using Annotated , we can store that Annotated value in a variable and use it in multiple places: Python 3.10+ from typing import Annotated from fastapi import Depends , FastAPI app = FastAPI () async def common_parameters ( q : str | None = None , skip : int = 0 , limit : int = 100 ): return { \"q\" : q , \"skip\" : skip , \"limit\" : limit } CommonsDep = Annotated [ dict , Depends ( common_parameters )] @app . get ( \"/items/\" ) async def read_items ( commons : CommonsDep ): return commons @app . get ( \"/users/\" ) async def read_users ( commons : CommonsDep ): return commons Tip This is just standard Python, it's called a \"type alias\", it's actually not specific to FastAPI . But because FastAPI is based on the Python standards, including Annotated , you can use this trick in your code. \ud83d\ude0e The dependencies will keep working as expected, and the best part is that the type information will be preserved , which means that your editor will be able to keep providing you with autocompletion , inline errors , etc. The same for other tools like mypy . This will be especially useful when you use it in a large code base where you use the same dependencies over and over again in many path operations . To async or not to async \u00b6 As dependencies will also be called by FastAPI (the same as your path operation functions ), the same rules apply while defining your functions. You can use async def or normal def . And you can declare dependencies with async def inside of normal def path operation functions , or def dependencies inside of async def path operation functions , etc. It doesn't matter. FastAPI will know what to do. Note If you don't know, check the Async: \"In a hurry?\" section about async and await in the docs. Integrated with OpenAPI \u00b6 All the request declarations, validations and requirements of your dependencies (and sub-dependencies) will be integrated in the same OpenAPI schema. So, the interactive"
},
{
"id": "dependencies.txt-3",
"source": "dependencies.txt",
"text": "the same rules apply while defining your functions. You can use async def or normal def . And you can declare dependencies with async def inside of normal def path operation functions , or def dependencies inside of async def path operation functions , etc. It doesn't matter. FastAPI will know what to do. Note If you don't know, check the Async: \"In a hurry?\" section about async and await in the docs. Integrated with OpenAPI \u00b6 All the request declarations, validations and requirements of your dependencies (and sub-dependencies) will be integrated in the same OpenAPI schema. So, the interactive docs will have all the information from these dependencies too: Simple usage \u00b6 If you look at it, path operation functions are declared to be used whenever a path and operation matches, and then FastAPI takes care of calling the function with the correct parameters, extracting the data from the request. Actually, all (or most) of the web frameworks work in this same way. You never call those functions directly. They are called by your framework (in this case, FastAPI ). With the Dependency Injection system, you can also tell FastAPI that your path operation function also \"depends\" on something else that should be executed before your path operation function , and FastAPI will take care of executing it and \"injecting\" the results. Other common terms for this same idea of \"dependency injection\" are: resources providers services injectables components FastAPI plug-ins \u00b6 Integrations and \"plug-ins\" can be built using the Dependency Injection system. But in fact, there is actually no need to create \"plug-ins\" , as by using dependencies it's possible to declare an infinite number of integrations and interactions that become available to your path operation functions . And dependencies can be created in a very simple and intuitive way that allows you to just import the Python packages you need, and integrate them with your API functions in a couple of lines of code, literally . You will see examples of this in the next chapters, about relational and NoSQL databases, security, etc. FastAPI compatibility \u00b6 The simplicity of the dependency injection system makes FastAPI compatible with: all the relational databases NoSQL databases external packages external APIs authentication and authorization systems API usage monitoring systems response data injection systems etc. Simple and Powerful \u00b6 Although the hierarchical dependency injection system is very simple to define and use, it's still very powerful. You can define dependencies that in turn can define dependencies themselves. In the end, a hierarchical tree of dependencies is built, and the Dependency Injection system takes care of solving all these dependencies for you (and their sub-dependencies) and providing (injecting) the results at each step. For example, let's say you have 4 API endpoints ( path operations ): /items/public/ /items/private/ /users/{user_id}/activate /items/pro/ then you could add different permission requirements for each of them just with dependencies and sub-dependencies: graph TB current_user([\"current_user\"]) active_user([\"active_user\"]) admin_user([\"admin_user\"]) paying_user([\"paying_user\"]) public[\"/items/public/\"] private[\"/items/private/\"] activate_user[\"/users/{user_id}/activate\"] pro_items[\"/items/pro/\"] current_user --> active_user active_user --> admin_user active_user --> paying_user current_user --> public active_user --> private admin_user --> activate_user paying_user --> pro_items Integrated with OpenAPI \u00b6 All these dependencies, while declaring their requirements, also add parameters, validations, etc. to your path operations . FastAPI will take care of adding it all to the OpenAPI schema, so that it is shown in the interactive documentation systems."
},
{
"id": "dependencies.txt-4",
"source": "dependencies.txt",
"text": "paying_user current_user --> public active_user --> private admin_user --> activate_user paying_user --> pro_items Integrated with OpenAPI \u00b6 All these dependencies, while declaring their requirements, also add parameters, validations, etc. to your path operations . FastAPI will take care of adding it all to the OpenAPI schema, so that it is shown in the interactive documentation systems."
},
{
"id": "path-params.txt-0",
"source": "path-params.txt",
"text": "Path Parameters \u00b6 You can declare path \"parameters\" or \"variables\" with the same syntax used by Python format strings: Python 3.10+ from fastapi import FastAPI app = FastAPI () @app . get ( \"/items/ {item_id} \" ) async def read_item ( item_id ): return { \"item_id\" : item_id } The value of the path parameter item_id will be passed to your function as the argument item_id . So, if you run this example and go to http://127.0.0.1:8000/items/foo , you will see a response of: { \"item_id\" : \"foo\" } Path parameters with types \u00b6 You can declare the type of a path parameter in the function, using standard Python type annotations: Python 3.10+ from fastapi import FastAPI app = FastAPI () @app . get ( \"/items/ {item_id} \" ) async def read_item ( item_id : int ): return { \"item_id\" : item_id } In this case, item_id is declared to be an int . Tip This will give you editor support inside of your function, with error checks, completion, etc. Data conversion \u00b6 If you run this example and open your browser at http://127.0.0.1:8000/items/3 , you will see a response of: { \"item_id\" : 3 } Tip Notice that the value your function received (and returned) is 3 , as a Python int , not a string \"3\" . So, with that type declaration, FastAPI gives you automatic request \"parsing\" . Data validation \u00b6 But if you go to the browser at http://127.0.0.1:8000/items/foo , you will see a nice HTTP error of: { \"detail\" : [ { \"type\" : \"int_parsing\" , \"loc\" : [ \"path\" , \"item_id\" ], \"msg\" : \"Input should be a valid integer, unable to parse string as an integer\" , \"input\" : \"foo\" } ] } because the path parameter item_id had a value of \"foo\" , which is not an int . The same error would appear if you provided a float instead of an int , as in: http://127.0.0.1:8000/items/4.2 Tip So, with the same Python type declaration, FastAPI gives you data validation. Notice that the error also clearly states exactly the point where the validation didn't pass. This is incredibly helpful while developing and debugging code that interacts with your API. Documentation \u00b6 And when you open your browser at http://127.0.0.1:8000/docs , you will see an automatic, interactive, API documentation like: Tip Again, just with that same Python type declaration, FastAPI gives you automatic, interactive documentation (integrating Swagger UI). Notice that the path parameter is declared to be an integer. Standards-based benefits, alternative documentation \u00b6 And because the generated schema is from the OpenAPI standard, there are many compatible tools. Because of this, FastAPI itself provides an alternative API documentation (using ReDoc), which you can access at http://127.0.0.1:8000/redoc : The same way, there are many compatible tools. Including code generation tools for many languages. Pydantic \u00b6 All the data validation is performed under the hood by Pydantic , so you get all the benefits from it. And you know you are in good hands. You can use the same type declarations with str , float , bool and many other complex data types. Several of these are explored in the next chapters of the tutorial. Order matters \u00b6 When creating path operations , you can find situations where you have a fixed path. Like /users/me , let's say that it's to get data about the current user. And then you can also have a path /users/{user_id} to get data about a specific user by some user ID. Because path operations are evaluated in order, you need to make sure that the path for /users/me"
},
{
"id": "path-params.txt-1",
"source": "path-params.txt",
"text": "You can use the same type declarations with str , float , bool and many other complex data types. Several of these are explored in the next chapters of the tutorial. Order matters \u00b6 When creating path operations , you can find situations where you have a fixed path. Like /users/me , let's say that it's to get data about the current user. And then you can also have a path /users/{user_id} to get data about a specific user by some user ID. Because path operations are evaluated in order, you need to make sure that the path for /users/me is declared before the one for /users/{user_id} : Python 3.10+ from fastapi import FastAPI app = FastAPI () @app . get ( \"/users/me\" ) async def read_user_me (): return { \"user_id\" : \"the current user\" } @app . get ( \"/users/ {user_id} \" ) async def read_user ( user_id : str ): return { \"user_id\" : user_id } Otherwise, the path for /users/{user_id} would match also for /users/me , \"thinking\" that it's receiving a parameter user_id with a value of \"me\" . Similarly, you cannot redefine a path operation: Python 3.10+ from fastapi import FastAPI app = FastAPI () @app . get ( \"/users\" ) async def read_users (): return [ \"Rick\" , \"Morty\" ] @app . get ( \"/users\" ) async def read_users2 (): return [ \"Bean\" , \"Elfo\" ] The first one will always be used since the path matches first. Predefined values \u00b6 If you have a path operation that receives a path parameter , but you want the possible valid path parameter values to be predefined, you can use a standard Python Enum . Create an Enum class \u00b6 Import Enum and create a sub-class that inherits from str and from Enum . By inheriting from str the API docs will be able to know that the values must be of type string and will be able to render correctly. Then create class attributes with fixed values, which will be the available valid values: Python 3.10+ from enum import Enum from fastapi import FastAPI class ModelName ( str , Enum ): alexnet = \"alexnet\" resnet = \"resnet\" lenet = \"lenet\" app = FastAPI () @app . get ( \"/models/ {model_name} \" ) async def get_model ( model_name : ModelName ): if model_name is ModelName . alexnet : return { \"model_name\" : model_name , \"message\" : \"Deep Learning FTW!\" } if model_name . value == \"lenet\" : return { \"model_name\" : model_name , \"message\" : \"LeCNN all the images\" } return { \"model_name\" : model_name , \"message\" : \"Have some residuals\" } Tip If you are wondering, \"AlexNet\", \"ResNet\", and \"LeNet\" are just names of Machine Learning models . Declare a path parameter \u00b6 Then create a path parameter with a type annotation using the enum class you created ( ModelName ): Python 3.10+ from enum import Enum from fastapi import FastAPI class ModelName ( str , Enum ): alexnet = \"alexnet\" resnet = \"resnet\" lenet = \"lenet\" app = FastAPI () @app . get ( \"/models/ {model_name} \" ) async def get_model ( model_name : ModelName ): if model_name is ModelName . alexnet : return { \"model_name\" : model_name , \"message\" : \"Deep Learning FTW!\" } if model_name . value == \"lenet\" : return { \"model_name\" : model_name , \"message\" : \"LeCNN all the images\" } return { \"model_name\" : model_name , \"message\" : \"Have some residuals\" } Check the docs \u00b6 Because the available values for the path parameter are predefined, the interactive docs can show them nicely: Working with Python enumerations \u00b6 The value"
},
{
"id": "path-params.txt-2",
"source": "path-params.txt",
"text": "\"lenet\" app = FastAPI () @app . get ( \"/models/ {model_name} \" ) async def get_model ( model_name : ModelName ): if model_name is ModelName . alexnet : return { \"model_name\" : model_name , \"message\" : \"Deep Learning FTW!\" } if model_name . value == \"lenet\" : return { \"model_name\" : model_name , \"message\" : \"LeCNN all the images\" } return { \"model_name\" : model_name , \"message\" : \"Have some residuals\" } Check the docs \u00b6 Because the available values for the path parameter are predefined, the interactive docs can show them nicely: Working with Python enumerations \u00b6 The value of the path parameter will be an enumeration member . Compare enumeration members \u00b6 You can compare it with the enumeration member in your created enum ModelName : Python 3.10+ from enum import Enum from fastapi import FastAPI class ModelName ( str , Enum ): alexnet = \"alexnet\" resnet = \"resnet\" lenet = \"lenet\" app = FastAPI () @app . get ( \"/models/ {model_name} \" ) async def get_model ( model_name : ModelName ): if model_name is ModelName . alexnet : return { \"model_name\" : model_name , \"message\" : \"Deep Learning FTW!\" } if model_name . value == \"lenet\" : return { \"model_name\" : model_name , \"message\" : \"LeCNN all the images\" } return { \"model_name\" : model_name , \"message\" : \"Have some residuals\" } Get the enumeration value \u00b6 You can get the actual value (a str in this case) using model_name.value , or in general, your_enum_member.value : Python 3.10+ from enum import Enum from fastapi import FastAPI class ModelName ( str , Enum ): alexnet = \"alexnet\" resnet = \"resnet\" lenet = \"lenet\" app = FastAPI () @app . get ( \"/models/ {model_name} \" ) async def get_model ( model_name : ModelName ): if model_name is ModelName . alexnet : return { \"model_name\" : model_name , \"message\" : \"Deep Learning FTW!\" } if model_name . value == \"lenet\" : return { \"model_name\" : model_name , \"message\" : \"LeCNN all the images\" } return { \"model_name\" : model_name , \"message\" : \"Have some residuals\" } Tip You could also access the value \"lenet\" with ModelName.lenet.value . Return enumeration members \u00b6 You can return enum members from your path operation , even nested in a JSON body (e.g. a dict ). They will be converted to their corresponding values (strings in this case) before returning them to the client: Python 3.10+ from enum import Enum from fastapi import FastAPI class ModelName ( str , Enum ): alexnet = \"alexnet\" resnet = \"resnet\" lenet = \"lenet\" app = FastAPI () @app . get ( \"/models/ {model_name} \" ) async def get_model ( model_name : ModelName ): if model_name is ModelName . alexnet : return { \"model_name\" : model_name , \"message\" : \"Deep Learning FTW!\" } if model_name . value == \"lenet\" : return { \"model_name\" : model_name , \"message\" : \"LeCNN all the images\" } return { \"model_name\" : model_name , \"message\" : \"Have some residuals\" } In your client you will get a JSON response like: { \"model_name\" : \"alexnet\" , \"message\" : \"Deep Learning FTW!\" } Path parameters containing paths \u00b6 Let's say you have a path operation with a path /files/{file_path} . But you need file_path itself to contain a path , like home/johndoe/myfile.txt . So, the URL for that file would be something like: /files/home/johndoe/myfile.txt . OpenAPI support \u00b6 OpenAPI doesn't support a way to declare a path parameter to contain a path inside, as that could lead to scenarios that are difficult to test and define. Nevertheless, you can still do it in FastAPI , using"
},
{
"id": "path-params.txt-3",
"source": "path-params.txt",
"text": "will get a JSON response like: { \"model_name\" : \"alexnet\" , \"message\" : \"Deep Learning FTW!\" } Path parameters containing paths \u00b6 Let's say you have a path operation with a path /files/{file_path} . But you need file_path itself to contain a path , like home/johndoe/myfile.txt . So, the URL for that file would be something like: /files/home/johndoe/myfile.txt . OpenAPI support \u00b6 OpenAPI doesn't support a way to declare a path parameter to contain a path inside, as that could lead to scenarios that are difficult to test and define. Nevertheless, you can still do it in FastAPI , using one of the internal tools from Starlette. And the docs would still work, although not adding any documentation telling that the parameter should contain a path. Path convertor \u00b6 Using an option directly from Starlette you can declare a path parameter containing a path using a URL like: /files/{file_path:path} In this case, the name of the parameter is file_path , and the last part, :path , tells it that the parameter should match any path . So, you can use it with: Python 3.10+ from fastapi import FastAPI app = FastAPI () @app . get ( \"/files/{file_path:path}\" ) async def read_file ( file_path : str ): return { \"file_path\" : file_path } Tip You might need the parameter to contain /home/johndoe/myfile.txt , with a leading slash ( / ). In that case, the URL would be: /files//home/johndoe/myfile.txt , with a double slash ( // ) between files and home . Recap \u00b6 With FastAPI , by using short, intuitive and standard Python type declarations, you get: Editor support: error checks, autocompletion, etc. Data \" parsing \" Data validation API annotation and automatic documentation And you only have to declare them once. That's probably the main visible advantage of FastAPI compared to alternative frameworks (apart from the raw performance)."
},
{
"id": "query-params.txt-0",
"source": "query-params.txt",
"text": "Query Parameters \u00b6 When you declare other function parameters that are not part of the path parameters, they are automatically interpreted as \"query\" parameters. Python 3.10+ from fastapi import FastAPI app = FastAPI () fake_items_db = [{ \"item_name\" : \"Foo\" }, { \"item_name\" : \"Bar\" }, { \"item_name\" : \"Baz\" }] @app . get ( \"/items/\" ) async def read_item ( skip : int = 0 , limit : int = 10 ): return fake_items_db [ skip : skip + limit ] The query is the set of key-value pairs that go after the ? in a URL, separated by & characters. For example, in the URL: http://127.0.0.1:8000/items/?skip=0&limit=10 ...the query parameters are: skip : with a value of 0 limit : with a value of 10 As they are part of the URL, they are \"naturally\" strings. But when you declare them with Python types (in the example above, as int ), they are converted to that type and validated against it. All the same processes that apply to path parameters also apply to query parameters: Editor support (obviously) Data \"parsing\" Data validation Automatic documentation Defaults \u00b6 As query parameters are not a fixed part of a path, they can be optional and can have default values. In the example above they have default values of skip=0 and limit=10 . So, going to the URL: http://127.0.0.1:8000/items/ would be the same as going to: http://127.0.0.1:8000/items/?skip=0&limit=10 But if you go to, for example: http://127.0.0.1:8000/items/?skip=20 The parameter values in your function will be: skip=20 : because you set it in the URL limit=10 : because that was the default value Optional parameters \u00b6 The same way, you can declare optional query parameters, by setting their default to None : Python 3.10+ from fastapi import FastAPI app = FastAPI () @app . get ( \"/items/ {item_id} \" ) async def read_item ( item_id : str , q : str | None = None ): if q : return { \"item_id\" : item_id , \"q\" : q } return { \"item_id\" : item_id } In this case, the function parameter q will be optional, and will be None by default. Tip Also notice that FastAPI is smart enough to notice that the path parameter item_id is a path parameter and q is not, so, it's a query parameter. Query parameter type conversion \u00b6 You can also declare bool types, and they will be converted: Python 3.10+ from fastapi import FastAPI app = FastAPI () @app . get ( \"/items/ {item_id} \" ) async def read_item ( item_id : str , q : str | None = None , short : bool = False ): item = { \"item_id\" : item_id } if q : item . update ({ \"q\" : q }) if not short : item . update ( { \"description\" : \"This is an amazing item that has a long description\" } ) return item In this case, if you go to: http://127.0.0.1:8000/items/foo?short=1 or http://127.0.0.1:8000/items/foo?short=True or http://127.0.0.1:8000/items/foo?short=true or http://127.0.0.1:8000/items/foo?short=on or http://127.0.0.1:8000/items/foo?short=yes or any other case variation (uppercase, first letter in uppercase, etc), your function will see the parameter short with a bool value of True . Otherwise as False . Multiple path and query parameters \u00b6 You can declare multiple path parameters and query parameters at the same time, FastAPI knows which is which. And you don't have to declare them in any specific order. They will be detected by name: Python 3.10+ from fastapi import FastAPI app = FastAPI () @app . get ( \"/users/ {user_id} /items/ {item_id} \" ) async def read_user_item ( user_id : int , item_id : str ,"
},
{
"id": "query-params.txt-1",
"source": "query-params.txt",
"text": "other case variation (uppercase, first letter in uppercase, etc), your function will see the parameter short with a bool value of True . Otherwise as False . Multiple path and query parameters \u00b6 You can declare multiple path parameters and query parameters at the same time, FastAPI knows which is which. And you don't have to declare them in any specific order. They will be detected by name: Python 3.10+ from fastapi import FastAPI app = FastAPI () @app . get ( \"/users/ {user_id} /items/ {item_id} \" ) async def read_user_item ( user_id : int , item_id : str , q : str | None = None , short : bool = False ): item = { \"item_id\" : item_id , \"owner_id\" : user_id } if q : item . update ({ \"q\" : q }) if not short : item . update ( { \"description\" : \"This is an amazing item that has a long description\" } ) return item Required query parameters \u00b6 When you declare a default value for non-path parameters (for now, we have only seen query parameters), then it is not required. If you don't want to add a specific value but just make it optional, set the default as None . But when you want to make a query parameter required, you can just not declare any default value: Python 3.10+ from fastapi import FastAPI app = FastAPI () @app . get ( \"/items/ {item_id} \" ) async def read_user_item ( item_id : str , needy : str ): item = { \"item_id\" : item_id , \"needy\" : needy } return item Here the query parameter needy is a required query parameter of type str . If you open in your browser a URL like: http://127.0.0.1:8000/items/foo-item ...without adding the required parameter needy , you will see an error like: { \"detail\" : [ { \"type\" : \"missing\" , \"loc\" : [ \"query\" , \"needy\" ], \"msg\" : \"Field required\" , \"input\" : null } ] } As needy is a required parameter, you would need to set it in the URL: http://127.0.0.1:8000/items/foo-item?needy=sooooneedy ...this would work: { \"item_id\" : \"foo-item\" , \"needy\" : \"sooooneedy\" } And of course, you can define some parameters as required, some as having a default value, and some entirely optional: Python 3.10+ from fastapi import FastAPI app = FastAPI () @app . get ( \"/items/ {item_id} \" ) async def read_user_item ( item_id : str , needy : str , skip : int = 0 , limit : int | None = None ): item = { \"item_id\" : item_id , \"needy\" : needy , \"skip\" : skip , \"limit\" : limit } return item In this case, there are 3 query parameters: needy , a required str . skip , an int with a default value of 0 . limit , an optional int . Tip You could also use Enum s the same way as with Path Parameters ."
},
{
"id": "request-body.txt-0",
"source": "request-body.txt",
"text": "Request Body \u00b6 When you need to send data from a client (let's say, a browser) to your API, you send it as a request body . A request body is data sent by the client to your API. A response body is the data your API sends to the client. Your API almost always has to send a response body. But clients don't necessarily need to send request bodies all the time, sometimes they only request a path, maybe with some query parameters, but don't send a body. To declare a request body, you use Pydantic models with all their power and benefits. Note To send data, you should use one of: POST (the most common), PUT , DELETE or PATCH . Sending a body with a GET request has an undefined behavior in the specifications, nevertheless, it is supported by FastAPI, only for very complex/extreme use cases. As it is discouraged, the interactive docs with Swagger UI won't show the documentation for the body when using GET , and proxies in the middle might not support it. Import Pydantic's BaseModel \u00b6 First, you need to import BaseModel from pydantic : Python 3.10+ from fastapi import FastAPI from pydantic import BaseModel class Item ( BaseModel ): name : str description : str | None = None price : float tax : float | None = None app = FastAPI () @app . post ( \"/items/\" ) async def create_item ( item : Item ): return item Create your data model \u00b6 Then you declare your data model as a class that inherits from BaseModel . Use standard Python types for all the attributes: Python 3.10+ from fastapi import FastAPI from pydantic import BaseModel class Item ( BaseModel ): name : str description : str | None = None price : float tax : float | None = None app = FastAPI () @app . post ( \"/items/\" ) async def create_item ( item : Item ): return item The same as when declaring query parameters, when a model attribute has a default value, it is not required. Otherwise, it is required. Use None to make it just optional. For example, this model above declares a JSON \" object \" (or Python dict ) like: { \"name\" : \"Foo\" , \"description\" : \"An optional description\" , \"price\" : 45.2 , \"tax\" : 3.5 } ...as description and tax are optional (with a default value of None ), this JSON \" object \" would also be valid: { \"name\" : \"Foo\" , \"price\" : 45.2 } Declare it as a parameter \u00b6 To add it to your path operation , declare it the same way you declared path and query parameters: Python 3.10+ from fastapi import FastAPI from pydantic import BaseModel class Item ( BaseModel ): name : str description : str | None = None price : float tax : float | None = None app = FastAPI () @app . post ( \"/items/\" ) async def create_item ( item : Item ): return item ...and declare its type as the model you created, Item . Results \u00b6 With just that Python type declaration, FastAPI will: Read the body of the request as JSON. Convert the corresponding types (if needed). Validate the data. If the data is invalid, it will return a nice and clear error, indicating exactly where and what was the incorrect data. Give you the received data in the parameter item . As you declared it in the function to be of type Item , you will also have all the editor support (completion, etc) for all"
},
{
"id": "request-body.txt-1",
"source": "request-body.txt",
"text": ": Item ): return item ...and declare its type as the model you created, Item . Results \u00b6 With just that Python type declaration, FastAPI will: Read the body of the request as JSON. Convert the corresponding types (if needed). Validate the data. If the data is invalid, it will return a nice and clear error, indicating exactly where and what was the incorrect data. Give you the received data in the parameter item . As you declared it in the function to be of type Item , you will also have all the editor support (completion, etc) for all of the attributes and their types. Generate JSON Schema definitions for your model, you can also use them anywhere else you like if it makes sense for your project. Those schemas will be part of the generated OpenAPI schema, and used by the automatic documentation UIs . Automatic docs \u00b6 The JSON Schemas of your models will be part of your OpenAPI generated schema, and will be shown in the interactive API docs: And will also be used in the API docs inside each path operation that needs them: Editor support \u00b6 In your editor, inside your function you will get type hints and completion everywhere (this wouldn't happen if you received a dict instead of a Pydantic model): You also get error checks for incorrect type operations: This is not by chance, the whole framework was built around that design. And it was thoroughly tested at the design phase, before any implementation, to ensure it would work with all the editors. There were even some changes to Pydantic itself to support this. The previous screenshots were taken with Visual Studio Code . But you would get the same editor support with PyCharm and most of the other Python editors: Tip If you use PyCharm as your editor, you can use the Pydantic PyCharm Plugin . It improves editor support for Pydantic models, with: auto-completion type checks refactoring searching inspections Use the model \u00b6 Inside of the function, you can access all the attributes of the model object directly: Python 3.10+ from fastapi import FastAPI from pydantic import BaseModel class Item ( BaseModel ): name : str description : str | None = None price : float tax : float | None = None app = FastAPI () @app . post ( \"/items/\" ) async def create_item ( item : Item ): item_dict = item . model_dump () if item . tax is not None : price_with_tax = item . price + item . tax item_dict . update ({ \"price_with_tax\" : price_with_tax }) return item_dict Request body + path parameters \u00b6 You can declare path parameters and request body at the same time. FastAPI will recognize that the function parameters that match path parameters should be taken from the path , and that function parameters that are declared to be Pydantic models should be taken from the request body . Python 3.10+ from fastapi import FastAPI from pydantic import BaseModel class Item ( BaseModel ): name : str description : str | None = None price : float tax : float | None = None app = FastAPI () @app . put ( \"/items/ {item_id} \" ) async def update_item ( item_id : int , item : Item ): return { \"item_id\" : item_id , ** item . model_dump ()} Request body + path + query parameters \u00b6 You can also declare body , path and query parameters, all at the same time. FastAPI will recognize each of them and take the data from the correct place. Python 3.10+ from"
},
{
"id": "request-body.txt-2",
"source": "request-body.txt",
"text": "class Item ( BaseModel ): name : str description : str | None = None price : float tax : float | None = None app = FastAPI () @app . put ( \"/items/ {item_id} \" ) async def update_item ( item_id : int , item : Item ): return { \"item_id\" : item_id , ** item . model_dump ()} Request body + path + query parameters \u00b6 You can also declare body , path and query parameters, all at the same time. FastAPI will recognize each of them and take the data from the correct place. Python 3.10+ from fastapi import FastAPI from pydantic import BaseModel class Item ( BaseModel ): name : str description : str | None = None price : float tax : float | None = None app = FastAPI () @app . put ( \"/items/ {item_id} \" ) async def update_item ( item_id : int , item : Item , q : str | None = None ): result = { \"item_id\" : item_id , ** item . model_dump ()} if q : result . update ({ \"q\" : q }) return result The function parameters will be recognized as follows: If the parameter is also declared in the path , it will be used as a path parameter. If the parameter is of a singular type (like int , float , str , bool , etc) it will be interpreted as a query parameter. If the parameter is declared to be of the type of a Pydantic model , it will be interpreted as a request body . Note FastAPI will know that the value of q is not required because of the default value = None . The str | None is not used by FastAPI to determine that the value is not required, it will know it's not required because it has a default value of = None . But adding the type annotations will allow your editor to give you better support and detect errors. Without Pydantic \u00b6 If you don't want to use Pydantic models, you can also use Body parameters. See the docs for Body - Multiple Parameters: Singular values in body ."
},
{
"id": "tutorial-first-steps.txt-0",
"source": "tutorial-first-steps.txt",
"text": "First Steps \u00b6 The simplest FastAPI file could look like this: Python 3.10+ from fastapi import FastAPI app = FastAPI () @app . get ( \"/\" ) async def root (): return { \"message\" : \"Hello World\" } Copy that to a file main.py . Run the live server: $ <font color = \"#4E9A06\" >fastapi</font> dev <span style=\"background-color:#009485\"><font color=\"#D3D7CF\"> FastAPI </font></span> Starting development server \ud83d\ude80 Searching for package file structure from directories with <font color=\"#3465A4\">__init__.py</font> files Importing from <font color=\"#75507B\">/home/user/code/</font><font color=\"#AD7FA8\">awesomeapp</font> <span style=\"background-color:#007166\"><font color=\"#D3D7CF\"> module </font></span> \ud83d\udc0d main.py <span style=\"background-color:#007166\"><font color=\"#D3D7CF\"> code </font></span> Importing the FastAPI app object from the module with the following code: <u style=\"text-decoration-style:solid\">from </u><u style=\"text-decoration-style:solid\"><b>main</b></u><u style=\"text-decoration-style:solid\"> import </u><u style=\"text-decoration-style:solid\"><b>app</b></u> <span style=\"background-color:#007166\"><font color=\"#D3D7CF\"> app </font></span> Using import string: <font color=\"#3465A4\">main:app</font> <span style=\"background-color:#007166\"><font color=\"#D3D7CF\"> server </font></span> Server started at <font color=\"#729FCF\"><u style=\"text-decoration-style:solid\">http://127.0.0.1:8000</u></font> <span style=\"background-color:#007166\"><font color=\"#D3D7CF\"> server </font></span> Documentation at <font color=\"#729FCF\"><u style=\"text-decoration-style:solid\">http://127.0.0.1:8000/docs</u></font> <span style=\"background-color:#007166\"><font color=\"#D3D7CF\"> tip </font></span> Running in development mode, for production use: <b>fastapi run</b> Logs: <span style=\"background-color:#007166\"><font color=\"#D3D7CF\"> INFO </font></span> Will watch for changes in these directories: <b>[</b><font color=\"#4E9A06\">'/home/user/code/awesomeapp'</font><b>]</b> <span style=\"background-color:#007166\"><font color=\"#D3D7CF\"> INFO </font></span> Uvicorn running on <font color=\"#729FCF\"><u style=\"text-decoration-style:solid\">http://127.0.0.1:8000</u></font> <b>(</b>Press CTRL+C to quit<b>)</b> <span style=\"background-color:#007166\"><font color=\"#D3D7CF\"> INFO </font></span> Started reloader process <b>[</b><font color=\"#34E2E2\"><b>383138</b></font><b>]</b> using WatchFiles <span style=\"background-color:#007166\"><font color=\"#D3D7CF\"> INFO </font></span> Started server process <b>[</b><font color=\"#34E2E2\"><b>383153</b></font><b>]</b> <span style=\"background-color:#007166\"><font color=\"#D3D7CF\"> INFO </font></span> Waiting for application startup. <span style=\"background-color:#007166\"><font color=\"#D3D7CF\"> INFO </font></span> Application startup complete. In the output, there's a line with something like: INFO: Uvicorn running on http://127.0.0.1:8000 (Press CTRL+C to quit) That line shows the URL where your app is being served on your local machine. Check it \u00b6 Open your browser at http://127.0.0.1:8000 . You will see the JSON response as: { \"message\" : \"Hello World\" } Interactive API docs \u00b6 Now go to http://127.0.0.1:8000/docs . You will see the automatic interactive API documentation (provided by Swagger UI ): Alternative API docs \u00b6 And now, go to http://127.0.0.1:8000/redoc . You will see the alternative automatic documentation (provided by ReDoc ): OpenAPI \u00b6 FastAPI generates a \"schema\" with all your API using the OpenAPI standard for defining APIs. \"Schema\" \u00b6 A \"schema\" is a definition or description of something. Not the code that implements it, but just an abstract description. API \"schema\" \u00b6 In this case, OpenAPI is a specification that dictates how to define a schema of your API. This schema definition includes your API paths, the possible parameters they take, etc. Data \"schema\" \u00b6 The term \"schema\" might also refer to the shape of some data, like a JSON content. In that case, it would mean the JSON attributes, and data types they have, etc. OpenAPI and JSON Schema \u00b6 OpenAPI defines an API schema for your API. And that schema includes definitions (or \"schemas\") of the data sent and received by your API using JSON Schema , the standard for JSON data schemas. Check the openapi.json \u00b6 If you are curious about what the raw OpenAPI schema looks like, FastAPI automatically generates a JSON (schema) with the descriptions of all your API. You can see it directly at: http://127.0.0.1:8000/openapi.json . It will show a JSON starting with something like: { \"openapi\" : \"3.1.0\" , \"info\" : { \"title\" : \"FastAPI\" , \"version\" : \"0.1.0\" }, \"paths\" : { \"/items/\" : { \"get\" : { \"responses\" : { \"200\" : { \"description\" : \"Successful Response\" , \"content\" : { \"application/json\" : { ... What is OpenAPI for \u00b6 The OpenAPI schema is what powers the two interactive documentation systems included. And there are dozens of alternatives, all based on OpenAPI. You could easily add any of those alternatives to your application built with FastAPI"
},
{
"id": "tutorial-first-steps.txt-1",
"source": "tutorial-first-steps.txt",
"text": "can see it directly at: http://127.0.0.1:8000/openapi.json . It will show a JSON starting with something like: { \"openapi\" : \"3.1.0\" , \"info\" : { \"title\" : \"FastAPI\" , \"version\" : \"0.1.0\" }, \"paths\" : { \"/items/\" : { \"get\" : { \"responses\" : { \"200\" : { \"description\" : \"Successful Response\" , \"content\" : { \"application/json\" : { ... What is OpenAPI for \u00b6 The OpenAPI schema is what powers the two interactive documentation systems included. And there are dozens of alternatives, all based on OpenAPI. You could easily add any of those alternatives to your application built with FastAPI . You could also use it to generate code automatically, for clients that communicate with your API. For example, frontend, mobile or IoT applications. Configure the app entrypoint in pyproject.toml \u00b6 You can configure where your app is located in a pyproject.toml file like: [tool.fastapi] entrypoint = \"main:app\" That entrypoint will tell the fastapi command that it should import the app like: from main import app If your code was structured like: . \u251c\u2500\u2500 backend \u2502 \u251c\u2500\u2500 main.py \u2502 \u251c\u2500\u2500 __init__.py Then you would set the entrypoint as: [tool.fastapi] entrypoint = \"backend.main:app\" which would be equivalent to: from backend.main import app fastapi dev with path or with --entrypoint CLI option \u00b6 You can also pass the file path to the fastapi dev command, and it will guess the FastAPI app object to use: $ fastapi dev main.py Or, you can also pass the --entrypoint option to the fastapi dev command: $ fastapi dev --entrypoint main:app But you would have to remember to pass the correct path\\entrypoint every time you call the fastapi command. Additionally, other tools might not be able to find it, for example the VS Code Extension or FastAPI Cloud , so it is recommended to use the entrypoint in pyproject.toml . Deploy your app (optional) \u00b6 You can optionally deploy your FastAPI app to FastAPI Cloud with a single command. \ud83d\ude80 $ fastapi deploy Deploying to FastAPI Cloud... \u2705 Deployment successful! \ud83d\udc14 Ready the chicken! Your app is ready at https://myapp.fastapicloud.dev The CLI will automatically detect your FastAPI application and deploy it to the cloud. If you are not logged in, your browser will open to complete the authentication process. That's it! Now you can access your app at that URL. \u2728 Recap, step by step \u00b6 Step 1: import FastAPI \u00b6 Python 3.10+ from fastapi import FastAPI app = FastAPI () @app . get ( \"/\" ) async def root (): return { \"message\" : \"Hello World\" } FastAPI is a Python class that provides all the functionality for your API. Technical Details FastAPI is a class that inherits directly from Starlette . You can use all the Starlette functionality with FastAPI too. Step 2: create a FastAPI \"instance\" \u00b6 Python 3.10+ from fastapi import FastAPI app = FastAPI () @app . get ( \"/\" ) async def root (): return { \"message\" : \"Hello World\" } Here the app variable will be an \"instance\" of the class FastAPI . This will be the main point of interaction to create all your API. Step 3: create a path operation \u00b6 Path \u00b6 \"Path\" here refers to the last part of the URL starting from the first / . So, in a URL like: https://example.com/items/foo ...the path would be: /items/foo Note A \"path\" is also commonly called an \"endpoint\" or a \"route\". While building an API, the \"path\" is the main way to separate \"concerns\" and \"resources\". Operation \u00b6 \"Operation\" here refers to one of the HTTP \"methods\". One of: POST GET PUT DELETE ...and the more"
},
{
"id": "tutorial-first-steps.txt-2",
"source": "tutorial-first-steps.txt",
"text": "the class FastAPI . This will be the main point of interaction to create all your API. Step 3: create a path operation \u00b6 Path \u00b6 \"Path\" here refers to the last part of the URL starting from the first / . So, in a URL like: https://example.com/items/foo ...the path would be: /items/foo Note A \"path\" is also commonly called an \"endpoint\" or a \"route\". While building an API, the \"path\" is the main way to separate \"concerns\" and \"resources\". Operation \u00b6 \"Operation\" here refers to one of the HTTP \"methods\". One of: POST GET PUT DELETE ...and the more exotic ones: OPTIONS HEAD PATCH TRACE In the HTTP protocol, you can communicate to each path using one (or more) of these \"methods\". When building APIs, you normally use these specific HTTP methods to perform a specific action. Normally you use: POST : to create data. GET : to read data. PUT : to update data. DELETE : to delete data. So, in OpenAPI, each of the HTTP methods is called an \"operation\". We are going to call them \" operations \" too. Define a path operation decorator \u00b6 Python 3.10+ from fastapi import FastAPI app = FastAPI () @app . get ( \"/\" ) async def root (): return { \"message\" : \"Hello World\" } The @app.get(\"/\") tells FastAPI that the function right below is in charge of handling requests that go to: the path / using a get operation @decorator Info That @something syntax in Python is called a \"decorator\". You put it on top of a function. Like a pretty decorative hat (I guess that's where the term came from). A \"decorator\" takes the function below and does something with it. In our case, this decorator tells FastAPI that the function below corresponds to the path / with an operation get . It is the \" path operation decorator \". You can also use the other operations: @app.post() @app.put() @app.delete() And the more exotic ones: @app.options() @app.head() @app.patch() @app.trace() Tip You are free to use each operation (HTTP method) as you wish. FastAPI doesn't enforce any specific meaning. The information here is presented as a guideline, not a requirement. For example, when using GraphQL you normally perform all the actions using only POST operations. Step 4: define the path operation function \u00b6 This is our \" path operation function \": path : is / . operation : is get . function : is the function below the \"decorator\" (below @app.get(\"/\") ). Python 3.10+ from fastapi import FastAPI app = FastAPI () @app . get ( \"/\" ) async def root (): return { \"message\" : \"Hello World\" } This is a Python function. It will be called by FastAPI whenever it receives a request to the URL \" / \" using a GET operation. In this case, it is an async function. You could also define it as a normal function instead of async def : Python 3.10+ from fastapi import FastAPI app = FastAPI () @app . get ( \"/\" ) def root (): return { \"message\" : \"Hello World\" } Note If you don't know the difference, check the Async: \"In a hurry?\" . Step 5: return the content \u00b6 Python 3.10+ from fastapi import FastAPI app = FastAPI () @app . get ( \"/\" ) async def root (): return { \"message\" : \"Hello World\" } You can return a dict , list , singular values as str , int , etc. You can also return Pydantic models (you'll see more about that later). There are many other objects and models that will be"
},
{
"id": "tutorial-first-steps.txt-3",
"source": "tutorial-first-steps.txt",
"text": ". get ( \"/\" ) def root (): return { \"message\" : \"Hello World\" } Note If you don't know the difference, check the Async: \"In a hurry?\" . Step 5: return the content \u00b6 Python 3.10+ from fastapi import FastAPI app = FastAPI () @app . get ( \"/\" ) async def root (): return { \"message\" : \"Hello World\" } You can return a dict , list , singular values as str , int , etc. You can also return Pydantic models (you'll see more about that later). There are many other objects and models that will be automatically converted to JSON (including ORMs, etc). Try using your favorite ones, it's highly probable that they are already supported. Step 6: Deploy it \u00b6 Deploy your app to FastAPI Cloud with one command: fastapi deploy . \ud83c\udf89 About FastAPI Cloud \u00b6 FastAPI Cloud is built by the same author and team behind FastAPI . It streamlines the process of building , deploying , and accessing an API with minimal effort. It brings the same developer experience of building apps with FastAPI to deploying them to the cloud. \ud83c\udf89 FastAPI Cloud is the primary sponsor and funding provider for the FastAPI and friends open source projects. \u2728 Deploy to other cloud providers \u00b6 FastAPI is open source and based on standards. You can deploy FastAPI apps to any cloud provider you choose. Follow your cloud provider's guides to deploy FastAPI apps with them. \ud83e\udd13 Recap \u00b6 Import FastAPI . Create an app instance. Write a path operation decorator using decorators like @app.get(\"/\") . Define a path operation function ; for example, def root(): ... . Run the development server using the command fastapi dev . Optionally deploy your app with fastapi deploy ."
}
]