Compare commits

..

5 Commits

Author SHA1 Message Date
Yurii Motov
60b988df41 Improve clarification for fixed 2026-01-21 10:57:02 +01:00
github-actions[bot]
2b26f7ba97 🎨 Auto format 2026-01-20 18:22:38 +00:00
Yurii Motov
b37b00ec1c Change abbr tag to dfn for definitions and notes 2026-01-20 18:55:00 +01:00
Yurii Motov
b4f60472c1 Fix abbreviations to follow the template 2026-01-20 18:39:40 +01:00
Yurii Motov
8568eb3571 Define style for <dfn> tag 2026-01-20 17:45:49 +01:00
58 changed files with 856 additions and 602 deletions

View File

@@ -34,7 +34,7 @@ The key features are:
* **Fast**: Very high performance, on par with **NodeJS** and **Go** (thanks to Starlette and Pydantic). [One of the fastest Python frameworks available](#performance).
* **Fast to code**: Increase the speed to develop features by about 200% to 300%. *
* **Fewer bugs**: Reduce about 40% of human (developer) induced errors. *
* **Intuitive**: Great editor support. <abbr title="also known as auto-complete, autocompletion, IntelliSense">Completion</abbr> everywhere. Less time debugging.
* **Intuitive**: Great editor support. <dfn title="also known as auto-complete, autocompletion, IntelliSense">Completion</dfn> everywhere. Less time debugging.
* **Easy**: Designed to be easy to use and learn. Less time reading docs.
* **Short**: Minimize code duplication. Multiple features from each parameter declaration. Fewer bugs.
* **Robust**: Get production-ready code. With automatic interactive documentation.
@@ -377,7 +377,7 @@ item: Item
* Validation of data:
* Automatic and clear errors when the data is invalid.
* Validation even for deeply nested JSON objects.
* <abbr title="also known as: serialization, parsing, marshalling">Conversion</abbr> of input data: coming from the network to Python data and types. Reading from:
* <dfn title="also known as: serialization, parsing, marshalling">Conversion</dfn> of input data: coming from the network to Python data and types. Reading from:
* JSON.
* Path parameters.
* Query parameters.
@@ -385,7 +385,7 @@ item: Item
* Headers.
* Forms.
* Files.
* <abbr title="also known as: serialization, parsing, marshalling">Conversion</abbr> of output data: converting from Python data and types to network data (as JSON):
* <dfn title="also known as: serialization, parsing, marshalling">Conversion</dfn> of output data: converting from Python data and types to network data (as JSON):
* Convert Python types (`str`, `int`, `float`, `bool`, `list`, etc).
* `datetime` objects.
* `UUID` objects.
@@ -448,7 +448,7 @@ For a more complete example including more features, see the <a href="https://fa
* Declaration of **parameters** from other different places as: **headers**, **cookies**, **form fields** and **files**.
* How to set **validation constraints** as `maximum_length` or `regex`.
* A very powerful and easy to use **<abbr title="also known as components, resources, providers, services, injectables">Dependency Injection</abbr>** system.
* A very powerful and easy to use **<dfn title="also known as components, resources, providers, services, injectables">Dependency Injection</dfn>** system.
* Security and authentication, including support for **OAuth2** with **JWT tokens** and **HTTP Basic** auth.
* More advanced (but equally easy) techniques for declaring **deeply nested JSON models** (thanks to Pydantic).
* **GraphQL** integration with <a href="https://strawberry.rocks" class="external-link" target="_blank">Strawberry</a> and other libraries.
@@ -533,7 +533,7 @@ Used by Starlette:
* <a href="https://www.python-httpx.org" target="_blank"><code>httpx</code></a> - Required if you want to use the `TestClient`.
* <a href="https://jinja.palletsprojects.com" target="_blank"><code>jinja2</code></a> - Required if you want to use the default template configuration.
* <a href="https://github.com/Kludex/python-multipart" target="_blank"><code>python-multipart</code></a> - Required if you want to support form <abbr title="converting the string that comes from an HTTP request into Python data">"parsing"</abbr>, with `request.form()`.
* <a href="https://github.com/Kludex/python-multipart" target="_blank"><code>python-multipart</code></a> - Required if you want to support form <dfn title="converting the string that comes from an HTTP request into Python data">"parsing"</dfn>, with `request.form()`.
Used by FastAPI:

View File

@@ -64,7 +64,7 @@ In that case, you can simply swap the standard `dataclasses` with `pydantic.data
6. Here we are returning a dictionary that contains `items` which is a list of dataclasses.
FastAPI is still capable of <abbr title="converting the data to a format that can be transmitted">serializing</abbr> the data to JSON.
FastAPI is still capable of <dfn title="converting the data to a format that can be transmitted">serializing</dfn> the data to JSON.
7. Here the `response_model` is using a type annotation of a list of `Author` dataclasses.

View File

@@ -141,7 +141,7 @@ You could do that with `openapi_extra`:
{* ../../docs_src/path_operation_advanced_configuration/tutorial006_py39.py hl[19:36, 39:40] *}
In this example, we didn't declare any Pydantic model. In fact, the request body is not even <abbr title="converted from some plain format, like bytes, into Python objects">parsed</abbr> as JSON, it is read directly as `bytes`, and the function `magic_data_reader()` would be in charge of parsing it in some way.
In this example, we didn't declare any Pydantic model. In fact, the request body is not even <dfn title="converted from some plain format, like bytes, into Python objects">parsed</dfn> as JSON, it is read directly as `bytes`, and the function `magic_data_reader()` would be in charge of parsing it in some way.
Nevertheless, we can declare the expected schema for the request body.

View File

@@ -6,29 +6,13 @@ For that, you can use the `WSGIMiddleware` and use it to wrap your WSGI applicat
## Using `WSGIMiddleware` { #using-wsgimiddleware }
/// info
This requires installing `a2wsgi` for example with `pip install a2wsgi`.
///
You need to import `WSGIMiddleware` from `a2wsgi`.
You need to import `WSGIMiddleware`.
Then wrap the WSGI (e.g. Flask) app with the middleware.
And then mount that under a path.
{* ../../docs_src/wsgi/tutorial001_py39.py hl[1,3,23] *}
/// note
Previously, it was recommended to use `WSGIMiddleware` from `fastapi.middleware.wsgi`, but it is now deprecated.
Its advised to use the `a2wsgi` package instead. The usage remains the same.
Just ensure that you have the `a2wsgi` package installed and import `WSGIMiddleware` correctly from `a2wsgi`.
///
{* ../../docs_src/wsgi/tutorial001_py39.py hl[2:3,3] *}
## Check it { #check-it }

View File

@@ -137,7 +137,7 @@ There are several Flask REST frameworks, but after investing the time and work i
### <a href="https://marshmallow.readthedocs.io/en/stable/" class="external-link" target="_blank">Marshmallow</a> { #marshmallow }
One of the main features needed by API systems is data "<abbr title="also called marshalling, conversion">serialization</abbr>" which is taking data from the code (Python) and converting it into something that can be sent through the network. For example, converting an object containing data from a database into a JSON object. Converting `datetime` objects into strings, etc.
One of the main features needed by API systems is data "<dfn title="also called marshalling, conversion">serialization</dfn>" which is taking data from the code (Python) and converting it into something that can be sent through the network. For example, converting an object containing data from a database into a JSON object. Converting `datetime` objects into strings, etc.
Another big feature needed by APIs is data validation, making sure that the data is valid, given certain parameters. For example, that some field is an `int`, and not some random string. This is especially useful for incoming data.
@@ -145,7 +145,7 @@ Without a data validation system, you would have to do all the checks by hand, i
These features are what Marshmallow was built to provide. It is a great library, and I have used it a lot before.
But it was created before there existed Python type hints. So, to define every <abbr title="the definition of how data should be formed">schema</abbr> you need to use specific utils and classes provided by Marshmallow.
But it was created before there existed Python type hints. So, to define every <dfn title="the definition of how data should be formed">schema</dfn> you need to use specific utils and classes provided by Marshmallow.
/// check | Inspired **FastAPI** to
@@ -155,7 +155,7 @@ Use code to define "schemas" that provide data types and validation, automatical
### <a href="https://webargs.readthedocs.io/en/latest/" class="external-link" target="_blank">Webargs</a> { #webargs }
Another big feature required by APIs is <abbr title="reading and converting to Python data">parsing</abbr> data from incoming requests.
Another big feature required by APIs is <dfn title="reading and converting to Python data">parsing</dfn> data from incoming requests.
Webargs is a tool that was made to provide that on top of several frameworks, including Flask.
@@ -419,7 +419,7 @@ Handle all the data validation, data serialization and automatic model documenta
### <a href="https://www.starlette.dev/" class="external-link" target="_blank">Starlette</a> { #starlette }
Starlette is a lightweight <abbr title="The new standard for building asynchronous Python web applications">ASGI</abbr> framework/toolkit, which is ideal for building high-performance asyncio services.
Starlette is a lightweight <dfn title="The new standard for building asynchronous Python web applications">ASGI</dfn> framework/toolkit, which is ideal for building high-performance asyncio services.
It is very simple and intuitive. It's designed to be easily extensible, and have modular components.

View File

@@ -203,3 +203,8 @@ Inspired by Termynal's CSS tricks with modifications
-webkit-box-shadow: 25px 0 0 #f4c025, 50px 0 0 #3ec930;
box-shadow: 25px 0 0 #f4c025, 50px 0 0 #3ec930;
}
.md-typeset dfn {
border-bottom: .05rem dotted var(--md-default-fg-color--light);
cursor: help;
}

View File

@@ -456,7 +456,7 @@ Without using containers, making applications run on startup and with restarts c
## Replication - Number of Processes { #replication-number-of-processes }
If you have a <abbr title="A group of machines that are configured to be connected and work together in some way.">cluster</abbr> of machines with **Kubernetes**, Docker Swarm Mode, Nomad, or another similar complex system to manage distributed containers on multiple machines, then you will probably want to **handle replication** at the **cluster level** instead of using a **process manager** (like Uvicorn with workers) in each container.
If you have a <dfn title="A group of machines that are configured to be connected and work together in some way.">cluster</dfn> of machines with **Kubernetes**, Docker Swarm Mode, Nomad, or another similar complex system to manage distributed containers on multiple machines, then you will probably want to **handle replication** at the **cluster level** instead of using a **process manager** (like Uvicorn with workers) in each container.
One of those distributed container management systems like Kubernetes normally has some integrated way of handling **replication of containers** while still supporting **load balancing** for the incoming requests. All at the **cluster level**.

View File

@@ -65,7 +65,7 @@ Here's an example of how an HTTPS API could look like, step by step, paying atte
It would probably all start by you **acquiring** some **domain name**. Then, you would configure it in a DNS server (possibly your same cloud provider).
You would probably get a cloud server (a virtual machine) or something similar, and it would have a <abbr title="That doesn't change">fixed</abbr> **public IP address**.
You would probably get a cloud server (a virtual machine) or something similar, and it would have a <dfn title="Doesn't change over time. Not dynamic">fixed</dfn> **public IP address**.
In the DNS server(s) you would configure a record (an "`A record`") to point **your domain** to the public **IP address of your server**.

View File

@@ -6,7 +6,7 @@
### Based on open standards { #based-on-open-standards }
* <a href="https://github.com/OAI/OpenAPI-Specification" class="external-link" target="_blank"><strong>OpenAPI</strong></a> for API creation, including declarations of <abbr title="also known as: endpoints, routes">path</abbr> <abbr title="also known as HTTP methods, as POST, GET, PUT, DELETE">operations</abbr>, parameters, request bodies, security, etc.
* <a href="https://github.com/OAI/OpenAPI-Specification" class="external-link" target="_blank"><strong>OpenAPI</strong></a> for API creation, including declarations of <dfn title="also known as: endpoints, routes">path</dfn> <dfn title="also known as HTTP methods, as POST, GET, PUT, DELETE">operations</dfn>, parameters, request bodies, security, etc.
* Automatic data model documentation with <a href="https://json-schema.org/" class="external-link" target="_blank"><strong>JSON Schema</strong></a> (as OpenAPI itself is based on JSON Schema).
* Designed around these standards, after a meticulous study. Instead of an afterthought layer on top.
* This also allows using automatic **client code generation** in many languages.
@@ -136,7 +136,7 @@ All built as reusable tools and components that are easy to integrate with your
### Dependency Injection { #dependency-injection }
FastAPI includes an extremely easy to use, but extremely powerful <abbr title='also known as "components", "resources", "services", "providers"'><strong>Dependency Injection</strong></abbr> system.
FastAPI includes an extremely easy to use, but extremely powerful <dfn title='also known as "components", "resources", "services", "providers"'><strong>Dependency Injection</strong></dfn> system.
* Even dependencies can have dependencies, creating a hierarchy or **"graph" of dependencies**.
* All **automatically handled** by the framework.
@@ -153,8 +153,8 @@ Any integration is designed to be so simple to use (with dependencies) that you
### Tested { #tested }
* 100% <abbr title="The amount of code that is automatically tested">test coverage</abbr>.
* 100% <abbr title="Python type annotations, with this your editor and external tools can give you better support">type annotated</abbr> code base.
* 100% <dfn title="The amount of code that is automatically tested">test coverage</dfn>.
* 100% <dfn title="Python type annotations, with this your editor and external tools can give you better support">type annotated</dfn> code base.
* Used in production applications.
## Starlette features { #starlette-features }
@@ -190,7 +190,7 @@ With **FastAPI** you get all of **Pydantic**'s features (as FastAPI is based on
* **No brainfuck**:
* No new schema definition micro-language to learn.
* If you know Python types you know how to use Pydantic.
* Plays nicely with your **<abbr title="Integrated Development Environment: similar to a code editor">IDE</abbr>/<abbr title="A program that checks for code errors">linter</abbr>/brain**:
* Plays nicely with your **<abbr title="Integrated Development Environment: similar to a code editor">IDE</abbr>/<dfn title="A program that checks for code errors">linter</dfn>/brain**:
* Because pydantic data structures are just instances of classes you define; auto-completion, linting, mypy and your intuition should all work properly with your validated data.
* Validate **complex structures**:
* Use of hierarchical Pydantic models, Python `typing`s `List` and `Dict`, etc.

View File

@@ -40,7 +40,7 @@ The key features are:
* **Fast**: Very high performance, on par with **NodeJS** and **Go** (thanks to Starlette and Pydantic). [One of the fastest Python frameworks available](#performance).
* **Fast to code**: Increase the speed to develop features by about 200% to 300%. *
* **Fewer bugs**: Reduce about 40% of human (developer) induced errors. *
* **Intuitive**: Great editor support. <abbr title="also known as auto-complete, autocompletion, IntelliSense">Completion</abbr> everywhere. Less time debugging.
* **Intuitive**: Great editor support. <dfn title="also known as auto-complete, autocompletion, IntelliSense">Completion</dfn> everywhere. Less time debugging.
* **Easy**: Designed to be easy to use and learn. Less time reading docs.
* **Short**: Minimize code duplication. Multiple features from each parameter declaration. Fewer bugs.
* **Robust**: Get production-ready code. With automatic interactive documentation.
@@ -374,7 +374,7 @@ item: Item
* Validation of data:
* Automatic and clear errors when the data is invalid.
* Validation even for deeply nested JSON objects.
* <abbr title="also known as: serialization, parsing, marshalling">Conversion</abbr> of input data: coming from the network to Python data and types. Reading from:
* <dfn title="also known as: serialization, parsing, marshalling">Conversion</dfn> of input data: coming from the network to Python data and types. Reading from:
* JSON.
* Path parameters.
* Query parameters.
@@ -382,7 +382,7 @@ item: Item
* Headers.
* Forms.
* Files.
* <abbr title="also known as: serialization, parsing, marshalling">Conversion</abbr> of output data: converting from Python data and types to network data (as JSON):
* <dfn title="also known as: serialization, parsing, marshalling">Conversion</dfn> of output data: converting from Python data and types to network data (as JSON):
* Convert Python types (`str`, `int`, `float`, `bool`, `list`, etc).
* `datetime` objects.
* `UUID` objects.
@@ -445,7 +445,7 @@ For a more complete example including more features, see the <a href="https://fa
* Declaration of **parameters** from other different places as: **headers**, **cookies**, **form fields** and **files**.
* How to set **validation constraints** as `maximum_length` or `regex`.
* A very powerful and easy to use **<abbr title="also known as components, resources, providers, services, injectables">Dependency Injection</abbr>** system.
* A very powerful and easy to use **<dfn title="also known as components, resources, providers, services, injectables">Dependency Injection</dfn>** system.
* Security and authentication, including support for **OAuth2** with **JWT tokens** and **HTTP Basic** auth.
* More advanced (but equally easy) techniques for declaring **deeply nested JSON models** (thanks to Pydantic).
* **GraphQL** integration with <a href="https://strawberry.rocks" class="external-link" target="_blank">Strawberry</a> and other libraries.
@@ -530,7 +530,7 @@ Used by Starlette:
* <a href="https://www.python-httpx.org" target="_blank"><code>httpx</code></a> - Required if you want to use the `TestClient`.
* <a href="https://jinja.palletsprojects.com" target="_blank"><code>jinja2</code></a> - Required if you want to use the default template configuration.
* <a href="https://github.com/Kludex/python-multipart" target="_blank"><code>python-multipart</code></a> - Required if you want to support form <abbr title="converting the string that comes from an HTTP request into Python data">"parsing"</abbr>, with `request.form()`.
* <a href="https://github.com/Kludex/python-multipart" target="_blank"><code>python-multipart</code></a> - Required if you want to support form <dfn title="converting the string that comes from an HTTP request into Python data">"parsing"</dfn>, with `request.form()`.
Used by FastAPI:

View File

@@ -2,7 +2,7 @@
Python has support for optional "type hints" (also called "type annotations").
These **"type hints"** or annotations are a special syntax that allow declaring the <abbr title="for example: str, int, float, bool">type</abbr> of a variable.
These **"type hints"** or annotations are a special syntax that allow declaring the <dfn title="for example: str, int, float, bool">type</dfn> of a variable.
By declaring types for your variables, editors and tools can give you better support.
@@ -34,7 +34,7 @@ The function does the following:
* Takes a `first_name` and `last_name`.
* Converts the first letter of each one to upper case with `title()`.
* <abbr title="Puts them together, as one. With the contents of one after the other.">Concatenates</abbr> them with a space in the middle.
* <dfn title="Puts them together, as one. With the contents of one after the other.">Concatenates</dfn> them with a space in the middle.
{* ../../docs_src/python_types/tutorial001_py39.py hl[2] *}
@@ -222,7 +222,7 @@ You can declare that a variable can be any of **several types**, for example, an
In Python 3.6 and above (including Python 3.10) you can use the `Union` type from `typing` and put inside the square brackets the possible types to accept.
In Python 3.10 there's also a **new syntax** where you can put the possible types separated by a <abbr title='also called "bitwise or operator", but that meaning is not relevant here'>vertical bar (`|`)</abbr>.
In Python 3.10 there's also a **new syntax** where you can put the possible types separated by a <dfn title='also called "bitwise or operator", but that meaning is not relevant here'>vertical bar (`|`)</dfn>.
//// tab | Python 3.10+
@@ -336,7 +336,7 @@ And the same as with previous Python versions, from the `typing` module:
* `Optional`
* ...and others.
In Python 3.10, as an alternative to using the generics `Union` and `Optional`, you can use the <abbr title='also called "bitwise or operator", but that meaning is not relevant here'>vertical bar (`|`)</abbr> to declare unions of types, that's a lot better and simpler.
In Python 3.10, as an alternative to using the generics `Union` and `Optional`, you can use the <dfn title='also called "bitwise or operator", but that meaning is not relevant here'>vertical bar (`|`)</dfn> to declare unions of types, that's a lot better and simpler.
////
@@ -411,7 +411,7 @@ Pydantic has a special behavior when you use `Optional` or `Union[Something, Non
## Type Hints with Metadata Annotations { #type-hints-with-metadata-annotations }
Python also has a feature that allows putting **additional <abbr title="Data about the data, in this case, information about the type, e.g. a description.">metadata</abbr>** in these type hints using `Annotated`.
Python also has a feature that allows putting **additional <dfn title="Data about the data, in this case, information about the type, e.g. a description.">metadata</dfn>** in these type hints using `Annotated`.
Since Python 3.9, `Annotated` is a part of the standard library, so you can import it from `typing`.

View File

@@ -35,3 +35,11 @@ It can be imported from `fastapi`:
```python
from fastapi.middleware.trustedhost import TrustedHostMiddleware
```
::: fastapi.middleware.wsgi.WSGIMiddleware
It can be imported from `fastapi`:
```python
from fastapi.middleware.wsgi import WSGIMiddleware
```

View File

@@ -18,10 +18,6 @@ hide:
### Translations
* 🌐 Update translations for ru (update-outdated). PR [#14693](https://github.com/fastapi/fastapi/pull/14693) by [@tiangolo](https://github.com/tiangolo).
* 🌐 Update translations for pt (update-outdated). PR [#14724](https://github.com/fastapi/fastapi/pull/14724) by [@tiangolo](https://github.com/tiangolo).
* 🌐 Update Korean LLM prompt. PR [#14740](https://github.com/fastapi/fastapi/pull/14740) by [@hard-coders](https://github.com/hard-coders).
* 🌐 Improve LLM prompt for Turkish translations. PR [#14728](https://github.com/fastapi/fastapi/pull/14728) by [@Kadermiyanyedi](https://github.com/Kadermiyanyedi).
* 🌐 Update portuguese llm-prompt.md. PR [#14702](https://github.com/fastapi/fastapi/pull/14702) by [@ceb10n](https://github.com/ceb10n).
* 🌐 Update LLM prompt instructions file for French. PR [#14618](https://github.com/fastapi/fastapi/pull/14618) by [@tiangolo](https://github.com/tiangolo).
* 🌐 Update translations for ko (add-missing). PR [#14699](https://github.com/fastapi/fastapi/pull/14699) by [@tiangolo](https://github.com/tiangolo).

View File

@@ -46,7 +46,7 @@ But even if you **fill the data** and click "Execute", because the docs UI works
In some special use cases (probably not very common), you might want to **restrict** the cookies that you want to receive.
Your API now has the power to control its own <abbr title="This is a joke, just in case. It has nothing to do with cookie consents, but it's funny that even the API can now reject the poor cookies. Have a cookie. 🍪">cookie consent</abbr>. 🤪🍪
Your API now has the power to control its own <dfn title="This is a joke, just in case. It has nothing to do with cookie consents, but it's funny that even the API can now reject the poor cookies. Have a cookie. 🍪">cookie consent</dfn>. 🤪🍪
You can use Pydantic's model configuration to `forbid` any `extra` fields:
@@ -54,9 +54,9 @@ You can use Pydantic's model configuration to `forbid` any `extra` fields:
If a client tries to send some **extra cookies**, they will receive an **error** response.
Poor cookie banners with all their effort to get your consent for the <abbr title="This is another joke. Don't pay attention to me. Have some coffee for your cookie. ☕">API to reject it</abbr>. 🍪
Poor cookie banners with all their effort to get your consent for the <dfn title="This is another joke. Don't pay attention to me. Have some coffee for your cookie. ☕">API to reject it</dfn>. 🍪
For example, if the client tries to send a `santa_tracker` cookie with a value of `good-list-please`, the client will receive an **error** response telling them that the `santa_tracker` <abbr title="Santa disapproves the lack of cookies. 🎅 Okay, no more cookie jokes.">cookie is not allowed</abbr>:
For example, if the client tries to send a `santa_tracker` cookie with a value of `good-list-please`, the client will receive an **error** response telling them that the `santa_tracker` <dfn title="Santa disapproves the lack of cookies. 🎅 Okay, no more cookie jokes.">cookie is not allowed</dfn>:
```json
{
@@ -73,4 +73,4 @@ For example, if the client tries to send a `santa_tracker` cookie with a value o
## Summary { #summary }
You can use **Pydantic models** to declare <abbr title="Have a last cookie before you go. 🍪">**cookies**</abbr> in **FastAPI**. 😎
You can use **Pydantic models** to declare <dfn title="Have a last cookie before you go. 🍪">**cookies**</dfn> in **FastAPI**. 😎

View File

@@ -1,6 +1,6 @@
# Dependencies with yield { #dependencies-with-yield }
FastAPI supports dependencies that do some <abbr title='sometimes also called "exit code", "cleanup code", "teardown code", "closing code", "context manager exit code", etc.'>extra steps after finishing</abbr>.
FastAPI supports dependencies that do some <dfn title='sometimes also called "exit code", "cleanup code", "teardown code", "closing code", "context manager exit code", etc.'>extra steps after finishing</dfn>.
To do this, use `yield` instead of `return`, and write the extra steps (code) after.

View File

@@ -1,6 +1,6 @@
# Dependencies { #dependencies }
**FastAPI** has a very powerful but intuitive **<abbr title="also known as components, resources, providers, services, injectables">Dependency Injection</abbr>** system.
**FastAPI** has a very powerful but intuitive **<dfn title="also known as components, resources, providers, services, injectables">Dependency Injection</dfn>** 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**.

View File

@@ -58,7 +58,7 @@ query_extractor --> query_or_cookie_extractor --> read_query
If one of your dependencies is declared multiple times for the same *path operation*, for example, multiple dependencies have a common sub-dependency, **FastAPI** will know to call that sub-dependency only once per request.
And it will save the returned value in a <abbr title="A utility/system to store computed/generated values, to reuse them instead of computing them again.">"cache"</abbr> and pass it to all the "dependants" that need it in that specific request, instead of calling the dependency multiple times for the same request.
And it will save the returned value in a <dfn title="A utility/system to store computed/generated values, to reuse them instead of computing them again.">"cache"</dfn> and pass it to all the "dependants" that need it in that specific request, instead of calling the dependency multiple times for the same request.
In an advanced scenario where you know you need the dependency to be called at every step (possibly multiple times) in the same request instead of using the "cached" value, you can set the parameter `use_cache=False` when using `Depends`:

View File

@@ -271,7 +271,7 @@ We are going to call them "**operations**" too.
The `@app.get("/")` tells **FastAPI** that the function right below is in charge of handling requests that go to:
* the path `/`
* using a <abbr title="an HTTP GET method"><code>get</code> operation</abbr>
* using a <dfn title="an HTTP GET method"><code>get</code> operation</dfn>
/// info | `@decorator` Info

View File

@@ -56,7 +56,7 @@ You can add a `summary` and `description`:
## Description from docstring { #description-from-docstring }
As descriptions tend to be long and cover multiple lines, you can declare the *path operation* description in the function <abbr title="a multi-line string as the first expression inside a function (not assigned to any variable) used for documentation">docstring</abbr> and **FastAPI** will read it from there.
As descriptions tend to be long and cover multiple lines, you can declare the *path operation* description in the function <dfn title="a multi-line string as the first expression inside a function (not assigned to any variable) used for documentation">docstring</dfn> and **FastAPI** will read it from there.
You can write <a href="https://en.wikipedia.org/wiki/Markdown" class="external-link" target="_blank">Markdown</a> in the docstring, it will be interpreted and displayed correctly (taking into account docstring indentation).
@@ -90,7 +90,7 @@ So, if you don't provide one, **FastAPI** will automatically generate one of "Su
## Deprecate a *path operation* { #deprecate-a-path-operation }
If you need to mark a *path operation* as <abbr title="obsolete, recommended not to use it">deprecated</abbr>, but without removing it, pass the parameter `deprecated`:
If you need to mark a *path operation* as <dfn title="obsolete, recommended not to use it">deprecated</dfn>, but without removing it, pass the parameter `deprecated`:
{* ../../docs_src/path_operation_configuration/tutorial006_py39.py hl[16] *}

View File

@@ -26,7 +26,7 @@ This will give you editor support inside of your function, with error checks, co
///
## Data <abbr title="also known as: serialization, parsing, marshalling">conversion</abbr> { #data-conversion }
## Data <dfn title="also known as: serialization, parsing, marshalling">conversion</dfn> { #data-conversion }
If you run this example and open your browser at <a href="http://127.0.0.1:8000/items/3" class="external-link" target="_blank">http://127.0.0.1:8000/items/3</a>, you will see a response of:
@@ -38,7 +38,7 @@ If you run this example and open your browser at <a href="http://127.0.0.1:8000/
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 <abbr title="converting the string that comes from an HTTP request into Python data">"parsing"</abbr>.
So, with that type declaration, **FastAPI** gives you automatic request <dfn title="converting the string that comes from an HTTP request into Python data">"parsing"</dfn>.
///
@@ -144,7 +144,7 @@ Then create class attributes with fixed values, which will be the available vali
/// tip
If you are wondering, "AlexNet", "ResNet", and "LeNet" are just names of Machine Learning <abbr title="Technically, Deep Learning model architectures">models</abbr>.
If you are wondering, "AlexNet", "ResNet", and "LeNet" are just names of Machine Learning <dfn title="Technically, Deep Learning model architectures">models</dfn>.
///
@@ -242,7 +242,7 @@ In that case, the URL would be: `/files//home/johndoe/myfile.txt`, with a double
With **FastAPI**, by using short, intuitive and standard Python type declarations, you get:
* Editor support: error checks, autocompletion, etc.
* Data "<abbr title="converting the string that comes from an HTTP request into Python data">parsing</abbr>"
* Data "<dfn title="converting the string that comes from an HTTP request into Python data">parsing</dfn>"
* Data validation
* API annotation and automatic documentation

View File

@@ -109,7 +109,7 @@ FastAPI will now:
## Alternative (old): `Query` as the default value { #alternative-old-query-as-the-default-value }
Previous versions of FastAPI (before <abbr title="before 2023-03">0.95.0</abbr>) required you to use `Query` as the default value of your parameter, instead of putting it in `Annotated`, there's a high chance that you will see code using it around, so I'll explain it to you.
Previous versions of FastAPI (before <dfn title="before 2023-03">0.95.0</dfn>) required you to use `Query` as the default value of your parameter, instead of putting it in `Annotated`, there's a high chance that you will see code using it around, so I'll explain it to you.
/// tip
@@ -192,7 +192,7 @@ You can also add a parameter `min_length`:
## Add regular expressions { #add-regular-expressions }
You can define a <abbr title="A regular expression, regex or regexp is a sequence of characters that define a search pattern for strings.">regular expression</abbr> `pattern` that the parameter should match:
You can define a <dfn title="A regular expression, regex or regexp is a sequence of characters that define a search pattern for strings.">regular expression</dfn> `pattern` that the parameter should match:
{* ../../docs_src/query_params_str_validations/tutorial004_an_py310.py hl[11] *}
@@ -372,7 +372,7 @@ Then you can declare an `alias`, and that alias is what will be used to find the
Now let's say you don't like this parameter anymore.
You have to leave it there a while because there are clients using it, but you want the docs to clearly show it as <abbr title="obsolete, recommended not to use it">deprecated</abbr>.
You have to leave it there a while because there are clients using it, but you want the docs to clearly show it as <dfn title="obsolete, recommended not to use it">deprecated</dfn>.
Then pass the parameter `deprecated=True` to `Query`:
@@ -402,7 +402,7 @@ Pydantic also has <a href="https://docs.pydantic.dev/latest/concepts/validators/
///
For example, this custom validator checks that the item ID starts with `isbn-` for an <abbr title="ISBN means International Standard Book Number">ISBN</abbr> book number or with `imdb-` for an <abbr title="IMDB (Internet Movie Database) is a website with information about movies">IMDB</abbr> movie URL ID:
For example, this custom validator checks that the item ID starts with `isbn-` for an <abbr title="International Standard Book Number">ISBN</abbr> book number or with `imdb-` for an <abbr title="Internet Movie Database: a website with information about movies">IMDB</abbr> movie URL ID:
{* ../../docs_src/query_params_str_validations/tutorial015_an_py310.py hl[5,16:19,24] *}
@@ -436,7 +436,7 @@ Did you notice? a string using `value.startswith()` can take a tuple, and it wil
#### A Random Item { #a-random-item }
With `data.items()` we get an <abbr title="Something we can iterate on with a for loop, like a list, set, etc.">iterable object</abbr> with tuples containing the key and value for each dictionary item.
With `data.items()` we get an <dfn title="Something we can iterate on with a for loop, like a list, set, etc.">iterable object</dfn> with tuples containing the key and value for each dictionary item.
We convert this iterable object into a proper `list` with `list(data.items())`.

View File

@@ -24,7 +24,7 @@ But when you declare them with Python types (in the example above, as `int`), th
All the same process that applied for path parameters also applies for query parameters:
* Editor support (obviously)
* Data <abbr title="converting the string that comes from an HTTP request into Python data">"parsing"</abbr>
* Data <dfn title="converting the string that comes from an HTTP request into Python data">"parsing"</dfn>
* Data validation
* Automatic documentation

View File

@@ -28,7 +28,7 @@ Create form parameters the same way you would for `Body` or `Query`:
For example, in one of the ways the OAuth2 specification can be used (called "password flow") it is required to send a `username` and `password` as form fields.
The <abbr title="specification">spec</abbr> requires the fields to be exactly named `username` and `password`, and to be sent as form fields, not JSON.
The <dfn title="specification">spec</dfn> requires the fields to be exactly named `username` and `password`, and to be sent as form fields, not JSON.
With `Form` you can declare the same configurations as with `Body` (and `Query`, `Path`, `Cookie`), including validation, examples, an alias (e.g. `user-name` instead of `username`), etc.

View File

@@ -201,7 +201,7 @@ This will also work because `RedirectResponse` is a subclass of `Response`, and
But when you return some other arbitrary object that is not a valid Pydantic type (e.g. a database object) and you annotate it like that in the function, FastAPI will try to create a Pydantic response model from that type annotation, and will fail.
The same would happen if you had something like a <abbr title='A union between multiple types means "any of these types".'>union</abbr> between different types where one or more of them are not valid Pydantic types, for example this would fail 💥:
The same would happen if you had something like a <dfn title='A union between multiple types means "any of these types".'>union</dfn> between different types where one or more of them are not valid Pydantic types, for example this would fail 💥:
{* ../../docs_src/response_model/tutorial003_04_py310.py hl[8] *}

View File

@@ -74,7 +74,7 @@ You can of course also pass multiple `examples`:
When you do this, the examples will be part of the internal **JSON Schema** for that body data.
Nevertheless, at the <abbr title="2023-08-26">time of writing this</abbr>, Swagger UI, the tool in charge of showing the docs UI, doesn't support showing multiple examples for the data in **JSON Schema**. But read below for a workaround.
Nevertheless, at the <dfn title="2023-08-26">time of writing this</dfn>, Swagger UI, the tool in charge of showing the docs UI, doesn't support showing multiple examples for the data in **JSON Schema**. But read below for a workaround.
### OpenAPI-specific `examples` { #openapi-specific-examples }

View File

@@ -53,7 +53,7 @@ $ cd awesome-project
## Create a Virtual Environment { #create-a-virtual-environment }
When you start working on a Python project **for the first time**, create a virtual environment **<abbr title="there are other options, this is a simple guideline">inside your project</abbr>**.
When you start working on a Python project **for the first time**, create a virtual environment **<dfn title="there are other options, this is a simple guideline">inside your project</dfn>**.
/// tip

View File

@@ -8,7 +8,6 @@ Language code: ko.
- Use polite, instructional Korean (e.g. 합니다/하세요 style).
- Keep the tone consistent with the existing Korean FastAPI docs.
- Do not translate “You” literally as “당신”. Use “여러분” where appropriate, or omit the subject if it sounds more natural in Korean.
### Headings

View File

@@ -1,8 +1,8 @@
# Arquivo de teste de LLM { #llm-test-file }
Este documento testa se o <abbr title="Large Language Model - Modelo de Linguagem de Grande Porte">LLM</abbr>, que traduz a documentação, entende o `general_prompt` em `scripts/translate.py` e o prompt específico do idioma em `docs/{language code}/llm-prompt.md`. O prompt específico do idioma é anexado ao `general_prompt`.
Este documento testa se o <abbr title="Large Language Model Modelo de Linguagem de Grande Porte">LLM</abbr>, que traduz a documentação, entende o `general_prompt` em `scripts/translate.py` e o prompt específico do idioma em `docs/{language code}/llm-prompt.md`. O prompt específico do idioma é anexado ao `general_prompt`.
Os testes adicionados aqui serão vistos por todos os designers dos prompts específicos de idioma.
Os testes adicionados aqui serão vistos por todos os autores dos prompts específicos de idioma.
Use da seguinte forma:
@@ -23,7 +23,7 @@ Este é um trecho de código: `foo`. E este é outro trecho de código: `bar`. E
////
//// tab | Informação
//// tab | Informações
O conteúdo dos trechos de código deve ser deixado como está.
@@ -45,9 +45,9 @@ O LLM provavelmente vai traduzir isso errado. O interessante é apenas se ele ma
////
//// tab | Informação
//// tab | Informações
O designer do prompt pode escolher se quer converter aspas neutras em aspas tipográficas. Também é aceitável deixá-las como estão.
O autor do prompt pode escolher se deseja converter aspas neutras em aspas tipográficas. Também é aceitável deixá-las como estão.
Veja, por exemplo, a seção `### Quotes` em `docs/de/llm-prompt.md`.
@@ -67,7 +67,7 @@ Pesado: `Yesterday, my friend wrote: "If you spell incorrectly correctly, you ha
////
//// tab | Informação
//// tab | Informações
... No entanto, as aspas dentro de trechos de código devem permanecer como estão.
@@ -95,24 +95,24 @@ $ <font color="#4E9A06">fastapi</font> run <u style="text-decoration-style:solid
...e outro exemplo de código de console...
```console
// Criar um diretório "Code"
// Crie um diretório "Code"
$ mkdir code
// Mudar para esse diretório
// Entre nesse diretório
$ cd code
```
...e um exemplo de código Python...
```Python
wont_work() # This won't work 😱
works(foo="bar") # This works 🎉
wont_work() # Isto não vai funcionar 😱
works(foo="bar") # Isto funciona 🎉
```
...e é isso.
////
//// tab | Informação
//// tab | Informações
O código em blocos de código não deve ser modificado, com exceção dos comentários.
@@ -154,7 +154,7 @@ Algum texto
////
//// tab | Informação
//// tab | Informações
Abas e blocos `Info`/`Note`/`Warning`/etc. devem ter a tradução do seu título adicionada após uma barra vertical (`|`).
@@ -181,7 +181,7 @@ O texto do link deve ser traduzido, o endereço do link deve apontar para a trad
////
//// tab | Informação
//// tab | Informações
Os links devem ser traduzidos, mas seus endereços devem permanecer inalterados. Uma exceção são links absolutos para páginas da documentação do FastAPI. Nesse caso, devem apontar para a tradução.
@@ -197,10 +197,10 @@ Aqui estão algumas coisas envolvidas em elementos HTML "abbr" (algumas são inv
### O abbr fornece uma frase completa { #the-abbr-gives-a-full-phrase }
* <abbr title="Getting Things Done">GTD</abbr>
* <abbr title="less than - menos que"><code>lt</code></abbr>
* <abbr title="XML Web Token">XWT</abbr>
* <abbr title="Parallel Server Gateway Interface - Interface de Gateway de Servidor Paralelo">PSGI</abbr>
* <abbr title="Getting Things Done Fazer as Coisas">GTD</abbr>
* <abbr title="menos que"><code>lt</code></abbr>
* <abbr title="XML Web Token Token Web XML">XWT</abbr>
* <abbr title="Parallel Server Gateway Interface Interface de Gateway de Servidor Paralelo">PSGI</abbr>
### O abbr fornece uma explicação { #the-abbr-gives-an-explanation }
@@ -209,12 +209,12 @@ Aqui estão algumas coisas envolvidas em elementos HTML "abbr" (algumas são inv
### O abbr fornece uma frase completa e uma explicação { #the-abbr-gives-a-full-phrase-and-an-explanation }
* <abbr title="Mozilla Developer Network: documentação para desenvolvedores, escrita pelo pessoal do Firefox">MDN</abbr>
* <abbr title="Input/Output: leitura ou escrita em disco, comunicações de rede.">I/O</abbr>.
* <abbr title="Mozilla Developer Network Rede de Desenvolvedores da Mozilla: documentação para desenvolvedores, escrita pelo pessoal do Firefox">MDN</abbr>
* <abbr title="Input/Output Entrada/Saída: leitura ou escrita em disco, comunicações de rede.">I/O</abbr>.
////
//// tab | Informação
//// tab | Informações
Os atributos "title" dos elementos "abbr" são traduzidos seguindo algumas instruções específicas.
@@ -228,7 +228,7 @@ Veja a seção `### HTML abbr elements` no prompt geral em `scripts/translate.py
//// tab | Teste
### Desenvolver uma webapp - um tutorial { #develop-a-webapp-a-tutorial }
### Desenvolver uma aplicação web - um tutorial { #develop-a-webapp-a-tutorial }
Olá.
@@ -242,7 +242,7 @@ Olá novamente.
////
//// tab | Informação
//// tab | Informações
A única regra rígida para títulos é que o LLM deixe a parte do hash dentro de chaves inalterada, o que garante que os links não quebrem.
@@ -494,9 +494,9 @@ Para algumas instruções específicas do idioma, veja, por exemplo, a seção `
////
//// tab | Informação
//// tab | Informações
Esta é uma lista não completa e não normativa de termos (principalmente) técnicos vistos na documentação. Pode ser útil para o designer do prompt descobrir para quais termos o LLM precisa de uma ajudinha. Por exemplo, quando ele continua revertendo uma boa tradução para uma tradução subótima. Ou quando tem problemas para conjugar/declinar um termo no seu idioma.
Esta é uma lista não completa e não normativa de termos (principalmente) técnicos vistos na documentação. Pode ser útil para o autor do prompt descobrir para quais termos o LLM precisa de uma ajudinha. Por exemplo, quando ele continua revertendo uma boa tradução para uma tradução subótima. Ou quando tem problemas para conjugar/declinar um termo no seu idioma.
Veja, por exemplo, a seção `### List of English terms and their preferred German translations` em `docs/de/llm-prompt.md`.

View File

@@ -10,7 +10,7 @@ Se você não é um "especialista" no OpenAPI, você provavelmente não precisa
Você pode definir o `operationId` do OpenAPI que será utilizado na sua *operação de rota* com o parâmetro `operation_id`.
Você deveria ter certeza que ele é único para cada operação.
Você precisa ter certeza que ele é único para cada operação.
{* ../../docs_src/path_operation_advanced_configuration/tutorial001_py39.py hl[6] *}
@@ -18,13 +18,13 @@ Você deveria ter certeza que ele é único para cada operação.
Se você quiser utilizar o nome das funções da sua API como `operationId`s, você pode iterar sobre todos esses nomes e sobrescrever o `operation_id` em cada *operação de rota* utilizando o `APIRoute.name` dela.
Você deveria fazer isso depois de adicionar todas as suas *operações de rota*.
Você deve fazer isso depois de adicionar todas as suas *operações de rota*.
{* ../../docs_src/path_operation_advanced_configuration/tutorial002_py39.py hl[2, 12:21, 24] *}
/// tip | Dica
Se você chamar `app.openapi()` manualmente, você deveria atualizar os `operationId`s antes dessa chamada.
Se você chamar `app.openapi()` manualmente, os `operationId`s devem ser atualizados antes dessa chamada.
///
@@ -44,11 +44,11 @@ Para excluir uma *operação de rota* do esquema OpenAPI gerado (e por consequê
## Descrição avançada a partir de docstring { #advanced-description-from-docstring }
Você pode limitar as linhas utilizadas a partir da docstring de uma *função de operação de rota* para o OpenAPI.
Você pode limitar as linhas utilizadas a partir de uma docstring de uma *função de operação de rota* para o OpenAPI.
Adicionar um `\f` (um caractere de escape para "form feed") faz com que o **FastAPI** trunque a saída usada para o OpenAPI até esse ponto.
Adicionar um `\f` (um caractere de escape para alimentação de formulário) faz com que o **FastAPI** restrinja a saída utilizada pelo OpenAPI até esse ponto.
Ele não será mostrado na documentação, mas outras ferramentas (como o Sphinx) serão capazes de utilizar o resto.
Ele não será mostrado na documentação, mas outras ferramentas (como o Sphinx) serão capazes de utilizar o resto do texto.
{* ../../docs_src/path_operation_advanced_configuration/tutorial004_py310.py hl[17:27] *}
@@ -131,38 +131,70 @@ E se você olhar o esquema OpenAPI resultante (na rota `/openapi.json` da sua AP
### Esquema de *operação de rota* do OpenAPI personalizado { #custom-openapi-path-operation-schema }
O dicionário em `openapi_extra` vai ser mesclado profundamente com o esquema OpenAPI gerado automaticamente para a *operação de rota*.
O dicionário em `openapi_extra` vai ter todos os seus níveis mesclados dentro do esquema OpenAPI gerado automaticamente para a *operação de rota*.
Então, você pode adicionar dados extras ao esquema gerado automaticamente.
Então, você pode adicionar dados extras para o esquema gerado automaticamente.
Por exemplo, você poderia decidir ler e validar a requisição com seu próprio código, sem usar as funcionalidades automáticas do FastAPI com o Pydantic, mas ainda assim querer definir a requisição no esquema OpenAPI.
Por exemplo, você poderia optar por ler e validar a requisição com seu próprio código, sem utilizar funcionalidades automatizadas do FastAPI com o Pydantic, mas você ainda pode quere definir a requisição no esquema OpenAPI.
Você pode fazer isso com `openapi_extra`:
{* ../../docs_src/path_operation_advanced_configuration/tutorial006_py39.py hl[19:36, 39:40] *}
Nesse exemplo, nós não declaramos nenhum modelo do Pydantic. Na verdade, o corpo da requisição não está nem mesmo <abbr title="converted from some plain format, like bytes, into Python objects - convertido de algum formato simples, como bytes, em objetos Python">analisado</abbr> como JSON, ele é lido diretamente como `bytes`, e a função `magic_data_reader()` seria a responsável por analisar ele de alguma forma.
Nesse exemplo, nós não declaramos nenhum modelo do Pydantic. Na verdade, o corpo da requisição não está nem mesmo <abbr title="convertido de um formato plano, como bytes, para objetos Python">analisado</abbr> como JSON, ele é lido diretamente como `bytes` e a função `magic_data_reader()` seria a responsável por analisar ele de alguma forma.
De toda forma, nós podemos declarar o esquema esperado para o corpo da requisição.
### Tipo de conteúdo do OpenAPI personalizado { #custom-openapi-content-type }
Utilizando esse mesmo truque, você pode usar um modelo Pydantic para definir o JSON Schema que é então incluído na seção do esquema personalizado do OpenAPI na *operação de rota*.
Utilizando esse mesmo truque, você pode utilizar um modelo Pydantic para definir o JSON Schema que é então incluído na seção do esquema personalizado do OpenAPI na *operação de rota*.
E você pode fazer isso até mesmo quando o tipo de dados na requisição não é JSON.
E você pode fazer isso até mesmo quando os dados da requisição não seguem o formato JSON.
Por exemplo, nesta aplicação nós não usamos a funcionalidade integrada ao FastAPI de extrair o JSON Schema dos modelos Pydantic nem a validação automática para JSON. Na verdade, estamos declarando o tipo de conteúdo da requisição como YAML, em vez de JSON:
Por exemplo, nesta aplicação nós não usamos a funcionalidade integrada ao FastAPI de extrair o JSON Schema dos modelos Pydantic nem a validação automática do JSON. Na verdade, estamos declarando o tipo do conteúdo da requisição como YAML, em vez de JSON:
//// tab | Pydantic v2
{* ../../docs_src/path_operation_advanced_configuration/tutorial007_py39.py hl[15:20, 22] *}
Entretanto, mesmo que não utilizemos a funcionalidade integrada por padrão, ainda estamos usando um modelo Pydantic para gerar um JSON Schema manualmente para os dados que queremos receber em YAML.
////
Então utilizamos a requisição diretamente e extraímos o corpo como `bytes`. Isso significa que o FastAPI não vai sequer tentar analisar o payload da requisição como JSON.
//// tab | Pydantic v1
E então no nosso código, nós analisamos o conteúdo YAML diretamente e, em seguida, estamos usando novamente o mesmo modelo Pydantic para validar o conteúdo YAML:
{* ../../docs_src/path_operation_advanced_configuration/tutorial007_pv1_py39.py hl[15:20, 22] *}
////
/// info | Informação
Na versão 1 do Pydantic, o método para obter o JSON Schema de um modelo é `Item.schema()`, na versão 2 do Pydantic, o método é `Item.model_json_schema()`.
///
Entretanto, mesmo que não utilizemos a funcionalidade integrada por padrão, ainda estamos usando um modelo Pydantic para gerar um JSON Schema manualmente para os dados que queremos receber no formato YAML.
Então utilizamos a requisição diretamente, e extraímos o corpo como `bytes`. Isso significa que o FastAPI não vai sequer tentar analisar o corpo da requisição como JSON.
E então no nosso código, nós analisamos o conteúdo YAML diretamente, e estamos utilizando o mesmo modelo Pydantic para validar o conteúdo YAML:
//// tab | Pydantic v2
{* ../../docs_src/path_operation_advanced_configuration/tutorial007_py39.py hl[24:31] *}
////
//// tab | Pydantic v1
{* ../../docs_src/path_operation_advanced_configuration/tutorial007_pv1_py39.py hl[24:31] *}
////
/// info | Informação
Na versão 1 do Pydantic, o método para analisar e validar um objeto era `Item.parse_obj()`, na versão 2 do Pydantic, o método é chamado de `Item.model_validate()`.
///
/// tip | Dica
Aqui reutilizamos o mesmo modelo do Pydantic.

View File

@@ -46,6 +46,12 @@ $ pip install "fastapi[all]"
</div>
/// info | Informação
No Pydantic v1 ele vinha incluído no pacote principal. Agora é distribuído como um pacote independente para que você possa optar por instalá-lo ou não, caso não precise dessa funcionalidade.
///
### Criar o objeto `Settings` { #create-the-settings-object }
Importe `BaseSettings` do Pydantic e crie uma subclasse, muito parecido com um modelo do Pydantic.
@@ -54,8 +60,24 @@ Da mesma forma que com modelos do Pydantic, você declara atributos de classe co
Você pode usar as mesmas funcionalidades e ferramentas de validação que usa em modelos do Pydantic, como diferentes tipos de dados e validações adicionais com `Field()`.
//// tab | Pydantic v2
{* ../../docs_src/settings/tutorial001_py39.py hl[2,5:8,11] *}
////
//// tab | Pydantic v1
/// info | Informação
No Pydantic v1 você importaria `BaseSettings` diretamente de `pydantic` em vez de `pydantic_settings`.
///
{* ../../docs_src/settings/tutorial001_pv1_py39.py hl[2,5:8,11] *}
////
/// tip | Dica
Se você quer algo rápido para copiar e colar, não use este exemplo, use o último abaixo.
@@ -193,6 +215,8 @@ APP_NAME="ChimichangApp"
E então atualizar seu `config.py` com:
//// tab | Pydantic v2
{* ../../docs_src/settings/app03_an_py39/config.py hl[9] *}
/// tip | Dica
@@ -201,6 +225,26 @@ O atributo `model_config` é usado apenas para configuração do Pydantic. Você
///
////
//// tab | Pydantic v1
{* ../../docs_src/settings/app03_an_py39/config_pv1.py hl[9:10] *}
/// tip | Dica
A classe `Config` é usada apenas para configuração do Pydantic. Você pode ler mais em <a href="https://docs.pydantic.dev/1.10/usage/model_config/" class="external-link" target="_blank">Pydantic Model Config</a>.
///
////
/// info | Informação
Na versão 1 do Pydantic a configuração era feita em uma classe interna `Config`, na versão 2 do Pydantic é feita em um atributo `model_config`. Esse atributo recebe um `dict`, e para ter autocompletar e erros inline você pode importar e usar `SettingsConfigDict` para definir esse `dict`.
///
Aqui definimos a configuração `env_file` dentro da sua classe `Settings` do Pydantic e definimos o valor como o nome do arquivo dotenv que queremos usar.
### Criando o `Settings` apenas uma vez com `lru_cache` { #creating-the-settings-only-once-with-lru-cache }

View File

@@ -2,23 +2,21 @@
Se você tem uma aplicação FastAPI antiga, pode estar usando o Pydantic versão 1.
O FastAPI versão 0.100.0 tinha suporte ao Pydantic v1 ou v2. Ele usaria aquele que você tivesse instalado.
O FastAPI tem suporte ao Pydantic v1 ou v2 desde a versão 0.100.0.
O FastAPI versão 0.119.0 introduziu suporte parcial ao Pydantic v1 a partir de dentro do Pydantic v2 (como `pydantic.v1`), para facilitar a migração para o v2.
Se você tiver o Pydantic v2 instalado, ele será utilizado. Se, em vez disso, tiver o Pydantic v1, será ele que será utilizado.
O FastAPI 0.126.0 removeu o suporte ao Pydantic v1, enquanto ainda oferece suporte a `pydantic.v1` por mais algum tempo.
O Pydantic v1 está agora descontinuado e o suporte a ele será removido nas próximas versões do FastAPI, você deveria migrar para o Pydantic v2. Assim, você terá as funcionalidades, melhorias e correções mais recentes.
/// warning | Atenção
A equipe do Pydantic interrompeu o suporte ao Pydantic v1 para as versões mais recentes do Python, a partir do **Python 3.14**.
Isso inclui `pydantic.v1`, que não é mais suportado no Python 3.14 e superiores.
Além disso, a equipe do Pydantic interrompeu o suporte ao Pydantic v1 para as versões mais recentes do Python, a partir do **Python 3.14**.
Se quiser usar as funcionalidades mais recentes do Python, você precisará garantir que usa o Pydantic v2.
///
Se você tem uma aplicação FastAPI antiga com Pydantic v1, aqui vou mostrar como migrá-la para o Pydantic v2, e as **funcionalidades no FastAPI 0.119.0** para ajudar em uma migração gradual.
Se você tem uma aplicação FastAPI antiga com Pydantic v1, aqui vou mostrar como migrá-la para o Pydantic v2 e as **novas funcionalidades no FastAPI 0.119.0** para ajudar em uma migração gradual.
## Guia oficial { #official-guide }
@@ -46,7 +44,7 @@ Depois disso, você pode rodar os testes e verificar se tudo funciona. Se funcio
## Pydantic v1 no v2 { #pydantic-v1-in-v2 }
O Pydantic v2 inclui tudo do Pydantic v1 como um submódulo `pydantic.v1`. Mas isso não é mais suportado em versões acima do Python 3.13.
O Pydantic v2 inclui tudo do Pydantic v1 como um submódulo `pydantic.v1`.
Isso significa que você pode instalar a versão mais recente do Pydantic v2 e importar e usar os componentes antigos do Pydantic v1 a partir desse submódulo, como se tivesse o Pydantic v1 antigo instalado.
@@ -68,7 +66,7 @@ Tenha em mente que, como a equipe do Pydantic não oferece mais suporte ao Pydan
### Pydantic v1 e v2 na mesma aplicação { #pydantic-v1-and-v2-on-the-same-app }
Não é **suportado** pelo Pydantic ter um modelo do Pydantic v2 com campos próprios definidos como modelos do Pydantic v1, ou vice-versa.
Não é suportado pelo Pydantic ter um modelo do Pydantic v2 com campos próprios definidos como modelos do Pydantic v1, ou vice-versa.
```mermaid
graph TB
@@ -88,7 +86,7 @@ graph TB
style V2Field fill:#f9fff3
```
...mas, você pode ter modelos separados usando Pydantic v1 e v2 na mesma aplicação.
...but, you can have separated models using Pydantic v1 and v2 in the same app.
```mermaid
graph TB
@@ -108,7 +106,7 @@ graph TB
style V2Field fill:#f9fff3
```
Em alguns casos, é até possível ter modelos Pydantic v1 e v2 na mesma **operação de rota** na sua aplicação FastAPI:
Em alguns casos, é até possível ter modelos Pydantic v1 e v2 na mesma operação de rota na sua aplicação FastAPI:
{* ../../docs_src/pydantic_v1_in_v2/tutorial003_an_py310.py hl[2:3,6,12,21:22] *}
@@ -124,7 +122,7 @@ Se você precisar usar algumas das ferramentas específicas do FastAPI para par
/// tip | Dica
Primeiro tente com o `bump-pydantic`, se seus testes passarem e isso funcionar, então você concluiu tudo com um único comando. ✨
Primeiro tente com o `bump-pydantic`; se seus testes passarem e isso funcionar, então você concluiu tudo com um único comando. ✨
///

View File

@@ -1,8 +1,8 @@
# Esquemas OpenAPI Separados para Entrada e Saída ou Não { #separate-openapi-schemas-for-input-and-output-or-not }
Desde que o **Pydantic v2** foi lançado, o OpenAPI gerado é um pouco mais exato e **correto** do que antes. 😎
Ao usar **Pydantic v2**, o OpenAPI gerado é um pouco mais exato e **correto** do que antes. 😎
De fato, em alguns casos, ele terá até **dois JSON Schemas** no OpenAPI para o mesmo modelo Pydantic, para entrada e saída, dependendo se eles possuem **valores padrão**.
Inclusive, em alguns casos, ele terá até **dois JSON Schemas** no OpenAPI para o mesmo modelo Pydantic, para entrada e saída, dependendo se eles possuem **valores padrão**.
Vamos ver como isso funciona e como alterar se for necessário.
@@ -95,8 +95,10 @@ O suporte para `separate_input_output_schemas` foi adicionado no FastAPI `0.102.
### Mesmo Esquema para Modelos de Entrada e Saída na Documentação { #same-schema-for-input-and-output-models-in-docs }
E agora haverá um único esquema para entrada e saída para o modelo, apenas `Item`, e ele terá `description` como **não obrigatório**:
E agora haverá um único esquema para entrada e saída para o modelo, apenas `Item`, e `description` **não será obrigatório**:
<div class="screenshot">
<img src="/img/tutorial/separate-openapi-schemas/image05.png">
</div>
Esse é o mesmo comportamento do Pydantic v1. 🤓

View File

@@ -40,8 +40,8 @@ Os recursos chave são:
* **Rápido**: alta performance, equivalente a **NodeJS** e **Go** (graças ao Starlette e Pydantic). [Um dos frameworks mais rápidos disponíveis](#performance).
* **Rápido para codar**: Aumenta a velocidade para desenvolver recursos entre 200% a 300%. *
* **Poucos bugs**: Reduz cerca de 40% de erros induzidos por humanos (desenvolvedores). *
* **Intuitivo**: Grande suporte a editores. <abbr title="também conhecido como auto-complete, autocompletion, IntelliSense">Completação</abbr> em todos os lugares. Menos tempo debugando.
* **Fácil**: Projetado para ser fácil de aprender e usar. Menos tempo lendo docs.
* **Intuitivo**: Grande suporte a _IDEs_. <abbr title="também conhecido como autocompletar, preenchimento automático, IntelliSense">Preenchimento automático</abbr> em todos os lugares. Menos tempo debugando.
* **Fácil**: Projetado para ser fácil de aprender e usar. Menos tempo lendo documentação.
* **Enxuto**: Minimize duplicação de código. Múltiplas funcionalidades para cada declaração de parâmetro. Menos bugs.
* **Robusto**: Tenha código pronto para produção. E com documentação interativa automática.
* **Baseado em padrões**: Baseado em (e totalmente compatível com) os padrões abertos para APIs: <a href="https://github.com/OAI/OpenAPI-Specification" class="external-link" target="_blank">OpenAPI</a> (anteriormente conhecido como Swagger) e <a href="https://json-schema.org/" class="external-link" target="_blank">JSON Schema</a>.
@@ -73,7 +73,7 @@ Os recursos chave são:
## Opiniões { #opinions }
"_[...] Estou usando **FastAPI** muito esses dias. [...] Estou na verdade planejando utilizar ele em todos os times de **serviços ML na Microsoft**. Alguns deles estão sendo integrados no _core_ do produto **Windows** e alguns produtos **Office**._"
"*[...] Estou usando **FastAPI** muito esses dias. [...] Estou na verdade planejando utilizar ele em todos os times de **serviços _Machine Learning_ na Microsoft**. Alguns deles estão sendo integrados no _core_ do produto **Windows** e alguns produtos **Office**.*"
<div style="text-align: right; margin-right: 10%;">Kabir Khan - <strong>Microsoft</strong> <a href="https://github.com/fastapi/fastapi/pull/26" target="_blank"><small>(ref)</small></a></div>
@@ -91,45 +91,39 @@ Os recursos chave são:
---
"_Estou muito entusiasmado com o **FastAPI**. É tão divertido!_"
"*Estou extremamente entusiasmado com o **FastAPI**. É tão divertido!*"
<div style="text-align: right; margin-right: 10%;">Brian Okken - <strong><a href="https://pythonbytes.fm/episodes/show/123/time-to-right-the-py-wrongs?time_in_sec=855" target="_blank">Python Bytes</a> apresentador do podcast</strong> <a href="https://x.com/brianokken/status/1112220079972728832" target="_blank"><small>(ref)</small></a></div>
<div style="text-align: right; margin-right: 10%;">Brian Okken - <strong><a href="https://pythonbytes.fm/episodes/show/123/time-to-right-the-py-wrongs?time_in_sec=855" target="_blank">Python Bytes</a> podcaster</strong> <a href="https://x.com/brianokken/status/1112220079972728832" target="_blank"><small>(ref)</small></a></div>
---
"_Honestamente, o que você construiu parece super sólido e refinado. De muitas formas, é o que eu queria que o **Hug** fosse - é realmente inspirador ver alguém construir isso._"
"*Honestamente, o que você construiu parece super sólido e rebuscado. De muitas formas, eu queria que o **Hug** fosse assim - é realmente inspirador ver alguém que construiu ele.*"
<div style="text-align: right; margin-right: 10%;">Timothy Crosley - <strong>criador do<a href="https://github.com/hugapi/hug" target="_blank">Hug</a></strong> <a href="https://news.ycombinator.com/item?id=19455465" target="_blank"><small>(ref)</small></a></div>
---
"_Se você está procurando aprender um **framework moderno** para construir APIs REST, dê uma olhada no **FastAPI** [...] É rápido, fácil de usar e fácil de aprender [...]_"
"*Se você está procurando aprender um **_framework_ moderno** para construir aplicações _REST_, dê uma olhada no **FastAPI** [...] É rápido, fácil de usar e fácil de aprender [...]*"
"_Nós trocamos nossas **APIs** por **FastAPI** [...] Acredito que você gostará dele [...]_"
"*Nós trocamos nossas **APIs** por **FastAPI** [...] Acredito que vocês gostarão dele [...]*"
<div style="text-align: right; margin-right: 10%;">Ines Montani - Matthew Honnibal - <strong>fundadores da <a href="https://explosion.ai" target="_blank">Explosion AI</a> - criadores da <a href="https://spacy.io" target="_blank">spaCy</a></strong> <a href="https://x.com/_inesmontani/status/1144173225322143744" target="_blank"><small>(ref)</small></a> - <a href="https://x.com/honnibal/status/1144031421859655680" target="_blank"><small>(ref)</small></a></div>
---
"_Se alguém estiver procurando construir uma API Python para produção, eu recomendaria fortemente o **FastAPI**. Ele é **lindamente projetado**, **simples de usar** e **altamente escalável**, e se tornou um **componente chave** para a nossa estratégia de desenvolvimento API first, impulsionando diversas automações e serviços, como o nosso Virtual TAC Engineer._"
"_Se alguém estiver procurando construir uma API Python para produção, eu recomendaria fortemente o **FastAPI**. Ele é **lindamente projetado**, **simples de usar** e **altamente escalável**. Ele se tornou um **componente chave** para a nossa estratégia API first de desenvolvimento e está impulsionando diversas automações e serviços, como o nosso Virtual TAC Engineer._"
<div style="text-align: right; margin-right: 10%;">Deon Pillsbury - <strong>Cisco</strong> <a href="https://www.linkedin.com/posts/deonpillsbury_cisco-cx-python-activity-6963242628536487936-trAp/" target="_blank"><small>(ref)</small></a></div>
---
## Mini documentário do FastAPI { #fastapi-mini-documentary }
Há um <a href="https://www.youtube.com/watch?v=mpR8ngthqiE" class="external-link" target="_blank">mini documentário do FastAPI</a> lançado no fim de 2025, você pode assisti-lo online:
<a href="https://www.youtube.com/watch?v=mpR8ngthqiE" target="_blank"><img src="https://fastapi.tiangolo.com/img/fastapi-documentary.jpg" alt="FastAPI Mini Documentary"></a>
## **Typer**, o FastAPI das interfaces de linhas de comando { #typer-the-fastapi-of-clis }
<a href="https://typer.tiangolo.com" target="_blank"><img src="https://typer.tiangolo.com/img/logo-margin/logo-margin-vector.svg" style="width: 20%;"></a>
Se você estiver construindo uma aplicação <abbr title="Command Line Interface - Interface de Linha de Comando">CLI</abbr> para ser utilizada no terminal ao invés de uma API web, dê uma olhada no <a href="https://typer.tiangolo.com/" class="external-link" target="_blank">**Typer**</a>.
Se você estiver construindo uma aplicação <abbr title="Command Line Interface Interface de Linha de Comando">CLI</abbr> para ser utilizada em um terminal ao invés de uma aplicação web, dê uma olhada no <a href="https://typer.tiangolo.com/" class="external-link" target="_blank">**Typer**</a>.
**Typer** é o irmão menor do FastAPI. E seu propósito é ser o **FastAPI das CLIs**. ⌨️ 🚀
**Typer** é o irmão menor do FastAPI. E seu propósito é ser o **FastAPI das _CLIs_**. ⌨️ 🚀
## Requisitos { #requirements }
@@ -261,10 +255,10 @@ Você verá a resposta JSON como:
Você acabou de criar uma API que:
* Recebe requisições HTTP nos _paths_ `/` e `/items/{item_id}`.
* Ambos _paths_ fazem <em>operações</em> `GET` (também conhecido como _métodos_ HTTP).
* O _path_ `/items/{item_id}` tem um _parâmetro de path_ `item_id` que deve ser um `int`.
* O _path_ `/items/{item_id}` tem um _parâmetro query_ `q` `str` opcional.
* Recebe requisições HTTP nas _rotas_ `/` e `/items/{item_id}`.
* Ambas _rotas_ fazem <em>operações</em> `GET` (também conhecido como _métodos_ HTTP).
* A _rota_ `/items/{item_id}` tem um _parâmetro de rota_ `item_id` que deve ser um `int`.
* A _rota_ `/items/{item_id}` tem um _parâmetro query_ `q` `str` opcional.
### Documentação Interativa da API { #interactive-api-docs }
@@ -284,7 +278,7 @@ Você verá a documentação automática alternativa (fornecida por <a href="htt
## Evoluindo o Exemplo { #example-upgrade }
Agora modifique o arquivo `main.py` para receber um corpo de uma requisição `PUT`.
Agora modifique o arquivo `main.py` para receber um corpo para uma requisição `PUT`.
Declare o corpo utilizando tipos padrão Python, graças ao Pydantic.
@@ -340,7 +334,7 @@ Agora vá para <a href="http://127.0.0.1:8000/docs" class="external-link" target
E agora, vá para <a href="http://127.0.0.1:8000/redoc" class="external-link" target="_blank">http://127.0.0.1:8000/redoc</a>.
* A documentação alternativa também irá refletir o novo parâmetro query e o corpo:
* A documentação alternativa também irá refletir o novo parâmetro da _query_ e o corpo:
![ReDoc](https://fastapi.tiangolo.com/img/index/index-06-redoc-02.png)
@@ -374,15 +368,15 @@ item: Item
* Validação de dados:
* Erros automáticos e claros quando o dado é inválido.
* Validação até para objetos JSON profundamente aninhados.
* <abbr title="também conhecido como: serialization, parsing, marshalling">Conversão</abbr> de dados de entrada: vindo da rede para dados e tipos Python. Consegue ler:
* <abbr title="também conhecido como: serialização, parsing, marshalling">Conversão</abbr> de dados de entrada: vindo da rede para dados e tipos Python. Consegue ler:
* JSON.
* Parâmetros de path.
* Parâmetros query.
* Cookies.
* Parâmetros de rota.
* Parâmetros de _query_ .
* _Cookies_.
* Cabeçalhos.
* Formulários.
* Arquivos.
* <abbr title="também conhecido como: serialization, parsing, marshalling">Conversão</abbr> de dados de saída: convertendo de tipos e dados Python para dados de rede (como JSON):
* <abbr title="também conhecido como: serialização, parsing, marshalling">Conversão</abbr> de dados de saída de tipos e dados Python para dados de rede (como JSON):
* Converte tipos Python (`str`, `int`, `float`, `bool`, `list` etc).
* Objetos `datetime`.
* Objetos `UUID`.
@@ -396,17 +390,17 @@ item: Item
Voltando ao código do exemplo anterior, **FastAPI** irá:
* Validar que existe um `item_id` no path para requisições `GET` e `PUT`.
* Validar que existe um `item_id` na rota para requisições `GET` e `PUT`.
* Validar que `item_id` é do tipo `int` para requisições `GET` e `PUT`.
* Se não for, o cliente verá um erro útil e claro.
* Verificar se existe um parâmetro query opcional nomeado como `q` (como em `http://127.0.0.1:8000/items/foo?q=somequery`) para requisições `GET`.
* Se não é validado, o cliente verá um útil, claro erro.
* Verificar se existe um parâmetro de _query_ opcional nomeado como `q` (como em `http://127.0.0.1:8000/items/foo?q=somequery`) para requisições `GET`.
* Como o parâmetro `q` é declarado com `= None`, ele é opcional.
* Sem o `None` ele seria obrigatório (como o corpo no caso de `PUT`).
* Sem o `None` ele poderia ser obrigatório (como o corpo no caso de `PUT`).
* Para requisições `PUT` para `/items/{item_id}`, lerá o corpo como JSON:
* Verifica que tem um atributo obrigatório `name` que deve ser `str`.
* Verifica que tem um atributo obrigatório `price` que tem que ser um `float`.
* Verifica que tem um atributo opcional `is_offer`, que deve ser um `bool`, se presente.
* Tudo isso também funcionaria para objetos JSON profundamente aninhados.
* Verifica que tem um atributo obrigatório `price` que deve ser `float`.
* Verifica que tem an atributo opcional `is_offer`, que deve ser `bool`, se presente.
* Tudo isso também funciona para objetos JSON profundamente aninhados.
* Converter de e para JSON automaticamente.
* Documentar tudo com OpenAPI, que poderá ser usado por:
* Sistemas de documentação interativos.
@@ -415,7 +409,7 @@ Voltando ao código do exemplo anterior, **FastAPI** irá:
---
Nós apenas arranhamos a superfície, mas você já tem ideia de como tudo funciona.
Nós apenas arranhamos a superfície, mas você já tem idéia de como tudo funciona.
Experimente mudar a seguinte linha:
@@ -443,22 +437,22 @@ Para um exemplo mais completo incluindo mais recursos, veja <a href="https://fas
**Alerta de Spoiler**: o tutorial - guia do usuário inclui:
* Declaração de **parâmetros** de diferentes lugares como: **cabeçalhos**, **cookies**, **campos de formulários** e **arquivos**.
* Como configurar **limitações de validação** como `maximum_length` ou `regex`.
* Um poderoso e fácil de usar sistema de **<abbr title="também conhecido como components, resources, providers, services, injectables">Injeção de Dependência</abbr>**.
* Segurança e autenticação, incluindo suporte para **OAuth2** com autenticação com **JWT tokens** e **HTTP Basic**.
* Declaração de **parâmetetros** de diferentes lugares como: **cabeçalhos**, **cookies**, **campos de formulários** e **arquivos**.
* Como configurar **Limitações de Validação** como `maximum_length` ou `regex`.
* Um poderoso e fácil de usar sistema de **<abbr title="também conhecido como componentes, recursos, fornecedores, serviços, injetáveis">Injeção de Dependência</abbr>**.
* Segurança e autenticação, incluindo suporte para **OAuth2** com autenticação **JWT tokens** e **HTTP Basic**.
* Técnicas mais avançadas (mas igualmente fáceis) para declaração de **modelos JSON profundamente aninhados** (graças ao Pydantic).
* Integrações **GraphQL** com o <a href="https://strawberry.rocks" class="external-link" target="_blank">Strawberry</a> e outras bibliotecas.
* Muitos recursos extras (graças ao Starlette) como:
* **WebSockets**
* testes extremamente fáceis baseados em HTTPX e `pytest`
* testes extrememamente fáceis baseados em HTTPX e `pytest`
* **CORS**
* **Cookie Sessions**
* ...e mais.
### Implemente sua aplicação (opcional) { #deploy-your-app-optional }
Você pode opcionalmente implantar sua aplicação FastAPI na <a href="https://fastapicloud.com" class="external-link" target="_blank">FastAPI Cloud</a>, vá e entre na lista de espera se ainda não o fez. 🚀
Você pode opcionalmente implantar sua aplicação FastAPI na <a href="https://fastapicloud.com" class="external-link" target="_blank">FastAPI Cloud</a>, inscreva-se na lista de espera se ainda não o fez. 🚀
Se você já tem uma conta na **FastAPI Cloud** (nós convidamos você da lista de espera 😉), pode implantar sua aplicação com um único comando.
@@ -512,7 +506,7 @@ Siga os tutoriais do seu provedor de nuvem para implantar aplicações FastAPI c
Testes de performance da _Independent TechEmpower_ mostram aplicações **FastAPI** rodando sob Uvicorn como <a href="https://www.techempower.com/benchmarks/#section=test&runid=7464e520-0dc2-473d-bd34-dbdfd7e85911&hw=ph&test=query&l=zijzen-7" class="external-link" target="_blank">um dos _frameworks_ Python mais rápidos disponíveis</a>, somente atrás de Starlette e Uvicorn (utilizados internamente pelo FastAPI). (*)
Para entender mais sobre isso, veja a seção <a href="https://fastapi.tiangolo.com/pt/benchmarks/" class="internal-link" target="_blank">Comparações</a>.
Para entender mais sobre performance, veja a seção <a href="https://fastapi.tiangolo.com/pt/benchmarks/" class="internal-link" target="_blank">Comparações</a>.
## Dependências { #dependencies }
@@ -520,7 +514,7 @@ O FastAPI depende do Pydantic e do Starlette.
### Dependências `standard` { #standard-dependencies }
Quando você instala o FastAPI com `pip install "fastapi[standard]"`, ele vem com o grupo `standard` de dependências opcionais:
Quando você instala o FastAPI com `pip install "fastapi[standard]"`, ele vêm com o grupo `standard` (padrão) de dependências opcionais:
Utilizado pelo Pydantic:
@@ -530,7 +524,7 @@ Utilizado pelo Starlette:
* <a href="https://www.python-httpx.org" target="_blank"><code>httpx</code></a> - Obrigatório caso você queira utilizar o `TestClient`.
* <a href="https://jinja.palletsprojects.com" target="_blank"><code>jinja2</code></a> - Obrigatório se você quer utilizar a configuração padrão de templates.
* <a href="https://github.com/Kludex/python-multipart" target="_blank"><code>python-multipart</code></a> - Obrigatório se você deseja suporte a <abbr title="converting the string that comes from an HTTP request into Python data - convertendo a string que vem de uma requisição HTTP em dados Python">"parsing"</abbr> de formulário, com `request.form()`.
* <a href="https://github.com/Kludex/python-multipart" target="_blank"><code>python-multipart</code></a> - Obrigatório se você deseja suporte a <abbr title="convertendo a string que vem de uma requisição HTTP em dados Python">"parsing"</abbr> de formulário, com `request.form()`.
Utilizado pelo FastAPI:
@@ -553,7 +547,7 @@ Existem algumas dependências adicionais que você pode querer instalar.
Dependências opcionais adicionais do Pydantic:
* <a href="https://docs.pydantic.dev/latest/usage/pydantic_settings/" target="_blank"><code>pydantic-settings</code></a> - para gerenciamento de configurações.
* <a href="https://docs.pydantic.dev/latest/usage/types/extra_types/extra_types/" target="_blank"><code>pydantic-extra-types</code></a> - para tipos extras a serem utilizados com o Pydantic.
* <a href="https://docs.pydantic.dev/latest/usage/types/extra_types/extra_types/" target="_blank"><code>pydantic-extra-types</code></a> - tipos extras para serem utilizados com o Pydantic.
Dependências opcionais adicionais do FastAPI:

View File

@@ -31,7 +31,7 @@ Digamos que você tenha uma estrutura de arquivos como esta:
/// tip | Dica
Existem vários arquivos `__init__.py`: um em cada diretório ou subdiretório.
Existem vários arquivos `__init__.py` presentes em cada diretório ou subdiretório.
Isso permite a importação de código de um arquivo para outro.
@@ -43,32 +43,32 @@ from app.routers import items
///
* O diretório `app` contém tudo. E possui um arquivo vazio `app/__init__.py`, então ele é um "pacote Python" (uma coleção de "módulos Python"): `app`.
* Ele contém um arquivo `app/main.py`. Como está dentro de um pacote Python (um diretório com um arquivo `__init__.py`), ele é um "módulo" desse pacote: `app.main`.
* Existe também um arquivo `app/dependencies.py`, assim como `app/main.py`, ele é um "módulo": `app.dependencies`.
* O diretório `app` contém todo o código da aplicação. Ele possui um arquivo `app/__init__.py` vazio, o que o torna um "pacote Python" (uma coleção de "módulos Python"): `app`.
* Dentro dele, o arquivo `app/main.py` está localizado em um pacote Python (diretório com `__init__.py`). Portanto, ele é um "módulo" desse pacote: `app.main`.
* Existem também um arquivo `app/dependencies.py`, assim como o `app/main.py`, ele é um "módulo": `app.dependencies`.
* Há um subdiretório `app/routers/` com outro arquivo `__init__.py`, então ele é um "subpacote Python": `app.routers`.
* O arquivo `app/routers/items.py` está dentro de um pacote, `app/routers/`, portanto é um submódulo: `app.routers.items`.
* O mesmo com `app/routers/users.py`, ele é outro submódulo: `app.routers.users`.
* Há também um subdiretório `app/internal/` com outro arquivo `__init__.py`, então ele é outro "subpacote Python": `app.internal`.
* O arquivo `app/routers/items.py` está dentro de um pacote, `app/routers/`, portanto, é um "submódulo": `app.routers.items`.
* O mesmo com `app/routers/users.py`, ele é outro submódulo: `app.routers.users`.
* Há também um subdiretório `app/internal/` com outro arquivo `__init__.py`, então ele é outro "subpacote Python":`app.internal`.
* E o arquivo `app/internal/admin.py` é outro submódulo: `app.internal.admin`.
<img src="/img/tutorial/bigger-applications/package.drawio.svg">
A mesma estrutura de arquivos com comentários:
```bash
```
.
├── app # "app" is a Python package
│   ├── __init__.py # this file makes "app" a "Python package"
│   ├── main.py # "main" module, e.g. import app.main
│   ├── dependencies.py # "dependencies" module, e.g. import app.dependencies
│   └── routers # "routers" is a "Python subpackage"
│   │ ├── __init__.py # makes "routers" a "Python subpackage"
│   │ ├── items.py # "items" submodule, e.g. import app.routers.items
│   │ └── users.py # "users" submodule, e.g. import app.routers.users
│   └── internal # "internal" is a "Python subpackage"
│   ├── __init__.py # makes "internal" a "Python subpackage"
│   └── admin.py # "admin" submodule, e.g. import app.internal.admin
├── app # "app" é um pacote Python
│   ├── __init__.py # este arquivo torna "app" um "pacote Python"
│   ├── main.py # "main" módulo, e.g. import app.main
│   ├── dependencies.py # "dependencies" módulo, e.g. import app.dependencies
│   └── routers # "routers" é um "subpacote Python"
│   │ ├── __init__.py # torna "routers" um "subpacote Python"
│   │ ├── items.py # "items" submódulo, e.g. import app.routers.items
│   │ └── users.py # "users" submódulo, e.g. import app.routers.users
│   └── internal # "internal" é um "subpacote Python"
│   ├── __init__.py # torna "internal" um "subpacote Python"
│   └── admin.py # "admin" submódulo, e.g. import app.internal.admin
```
## `APIRouter` { #apirouter }
@@ -79,11 +79,11 @@ Você quer manter as *operações de rota* relacionadas aos seus usuários separ
Mas ele ainda faz parte da mesma aplicação/web API **FastAPI** (faz parte do mesmo "pacote Python").
Você pode criar as *operações de rota* para esse módulo usando o `APIRouter`.
Você pode criar as *operações de rotas* para esse módulo usando o `APIRouter`.
### Importe `APIRouter` { #import-apirouter }
Você o importa e cria uma "instância" da mesma maneira que faria com a classe `FastAPI`:
você o importa e cria uma "instância" da mesma maneira que faria com a classe `FastAPI`:
{* ../../docs_src/bigger_applications/app_an_py39/routers/users.py hl[1,3] title["app/routers/users.py"] *}
@@ -91,7 +91,7 @@ Você o importa e cria uma "instância" da mesma maneira que faria com a classe
E então você o utiliza para declarar suas *operações de rota*.
Utilize-o da mesma maneira que utilizaria a classe `FastAPI`:
Utilize-o da mesma maneira que utilizaria a classe `FastAPI`:
{* ../../docs_src/bigger_applications/app_an_py39/routers/users.py hl[6,11,16] title["app/routers/users.py"] *}
@@ -151,7 +151,7 @@ Então, em vez de adicionar tudo isso a cada *operação de rota*, podemos adici
{* ../../docs_src/bigger_applications/app_an_py39/routers/items.py hl[5:10,16,21] title["app/routers/items.py"] *}
Como o path de cada *operação de rota* tem que começar com `/`, como em:
Como o caminho de cada *operação de rota* deve começar com `/`, como em:
```Python hl_lines="1"
@router.get("/{item_id}")
@@ -163,9 +163,9 @@ async def read_item(item_id: str):
Então, o prefixo neste caso é `/items`.
Também podemos adicionar uma list de `tags` e `responses` extras que serão aplicadas a todas as *operações de rota* incluídas neste router.
Também podemos adicionar uma lista de `tags` e `responses` extras que serão aplicadas a todas as *operações de rota* incluídas neste roteador.
E podemos adicionar uma list de `dependencies` que serão adicionadas a todas as *operações de rota* no router e serão executadas/resolvidas para cada request feita a elas.
E podemos adicionar uma lista de `dependencies` que serão adicionadas a todas as *operações de rota* no roteador e serão executadas/resolvidas para cada request feita a elas.
/// tip | Dica
@@ -173,7 +173,7 @@ Observe que, assim como [dependências em *decoradores de operação de rota*](d
///
O resultado final é que os paths dos itens agora são:
O resultado final é que os caminhos dos itens agora são:
* `/items/`
* `/items/{item_id}`
@@ -183,9 +183,9 @@ O resultado final é que os paths dos itens agora são:
* Elas serão marcadas com uma lista de tags que contêm uma única string `"items"`.
* Essas "tags" são especialmente úteis para os sistemas de documentação interativa automática (usando OpenAPI).
* Todas elas incluirão as `responses` predefinidas.
* Todas essas *operações de rota* terão a list de `dependencies` avaliada/executada antes delas.
* Todas essas *operações de rota* terão a lista de `dependencies` avaliada/executada antes delas.
* Se você também declarar dependências em uma *operação de rota* específica, **elas também serão executadas**.
* As dependências do router são executadas primeiro, depois as [`dependencies` no decorador](dependencies/dependencies-in-path-operation-decorators.md){.internal-link target=_blank} e, em seguida, as dependências de parâmetros normais.
* As dependências do roteador são executadas primeiro, depois as [`dependencies` no decorador](dependencies/dependencies-in-path-operation-decorators.md){.internal-link target=_blank} e, em seguida, as dependências de parâmetros normais.
* Você também pode adicionar [dependências de `Segurança` com `scopes`](../advanced/security/oauth2-scopes.md){.internal-link target=_blank}.
/// tip | Dica
@@ -246,7 +246,7 @@ from ..dependencies import get_token_header
significa:
* Começando no mesmo pacote em que este módulo (o arquivo `app/routers/items.py`) vive (o diretório `app/routers/`)...
* Começando no mesmo pacote em que este módulo (o arquivo `app/routers/items.py`) reside (o diretório `app/routers/`)...
* vá para o pacote pai (o diretório `app/`)...
* e lá, encontre o módulo `dependencies` (o arquivo em `app/dependencies.py`)...
* e dele, importe a função `get_token_header`.
@@ -283,9 +283,9 @@ Mas ainda podemos adicionar _mais_ `tags` que serão aplicadas a uma *operação
/// tip | Dica
Esta última operação de rota terá a combinação de tags: `["items", "custom"]`.
Esta última operação de caminho terá a combinação de tags: `["items", "custom"]`.
E também terá ambas as responses na documentação, uma para `404` e uma para `403`.
E também terá ambas as respostas na documentação, uma para `404` e uma para `403`.
///
@@ -325,7 +325,7 @@ from .routers import items, users
significa:
* Começando no mesmo pacote em que este módulo (o arquivo `app/main.py`) vive (o diretório `app/`)...
* Começando no mesmo pacote em que este módulo (o arquivo `app/main.py`) reside (o diretório `app/`)...
* procure o subpacote `routers` (o diretório em `app/routers/`)...
* e dele, importe o submódulo `items` (o arquivo em `app/routers/items.py`) e `users` (o arquivo em `app/routers/users.py`)...
@@ -376,7 +376,7 @@ Então, para poder usar ambos no mesmo arquivo, importamos os submódulos direta
{* ../../docs_src/bigger_applications/app_an_py39/main.py hl[5] title["app/main.py"] *}
### Inclua os `APIRouter`s para `users` e `items` { #include-the-apirouters-for-users-and-items }
### Inclua os `APIRouter`s para `usuários` e `itens` { #include-the-apirouters-for-users-and-items }
Agora, vamos incluir os `router`s dos submódulos `users` e `items`:
@@ -392,7 +392,7 @@ E `items.router` contém o `APIRouter` dentro do arquivo `app/routers/items.py`.
Com `app.include_router()` podemos adicionar cada `APIRouter` ao aplicativo principal `FastAPI`.
Ele incluirá todas as rotas daquele router como parte dele.
Ele incluirá todas as rotas daquele roteador como parte dele.
/// note | Detalhes Técnicos
@@ -404,7 +404,7 @@ Então, nos bastidores, ele realmente funcionará como se tudo fosse o mesmo apl
/// check | Verifique
Você não precisa se preocupar com desempenho ao incluir routers.
Você não precisa se preocupar com desempenho ao incluir roteadores.
Isso levará microssegundos e só acontecerá na inicialização.
@@ -453,7 +453,7 @@ e funcionará corretamente, junto com todas as outras *operações de rota* adic
/// note | Detalhes Técnicos Avançados
**Nota**: este é um detalhe muito técnico que você provavelmente pode **simplesmente pular**.
**Observação**: este é um detalhe muito técnico que você provavelmente pode **simplesmente pular**.
---
@@ -479,15 +479,15 @@ $ fastapi dev app/main.py
</div>
E abra a documentação em <a href="http://127.0.0.1:8000/docs" class="external-link" target="_blank">http://127.0.0.1:8000/docs</a>.
E abra os documentos em <a href="http://127.0.0.1:8000/docs" class="external-link" target="_blank">http://127.0.0.1:8000/docs</a>.
Você verá a documentação automática da API, incluindo os paths de todos os submódulos, usando os paths (e prefixos) corretos e as tags corretas:
Você verá a documentação automática da API, incluindo os caminhos de todos os submódulos, usando os caminhos (e prefixos) corretos e as tags corretas:
<img src="/img/tutorial/bigger-applications/image01.png">
## Inclua o mesmo router várias vezes com `prefix` diferentes { #include-the-same-router-multiple-times-with-different-prefix }
## Inclua o mesmo roteador várias vezes com `prefix` diferentes { #include-the-same-router-multiple-times-with-different-prefix }
Você também pode usar `.include_router()` várias vezes com o *mesmo* router usando prefixos diferentes.
Você também pode usar `.include_router()` várias vezes com o *mesmo* roteador usando prefixos diferentes.
Isso pode ser útil, por exemplo, para expor a mesma API sob prefixos diferentes, por exemplo, `/api/v1` e `/api/latest`.
@@ -495,10 +495,10 @@ Esse é um uso avançado que você pode não precisar, mas está lá caso precis
## Inclua um `APIRouter` em outro { #include-an-apirouter-in-another }
Da mesma forma que você pode incluir um `APIRouter` em uma aplicação `FastAPI`, você pode incluir um `APIRouter` em outro `APIRouter` usando:
Da mesma forma que você pode incluir um `APIRouter` em um aplicativo `FastAPI`, você pode incluir um `APIRouter` em outro `APIRouter` usando:
```Python
router.include_router(other_router)
```
Certifique-se de fazer isso antes de incluir `router` na aplicação `FastAPI`, para que as *operações de rota* de `other_router` também sejam incluídas.
Certifique-se de fazer isso antes de incluir `router` no aplicativo `FastAPI`, para que as *operações de rota* de `other_router` também sejam incluídas.

View File

@@ -1,6 +1,6 @@
# Corpo - Atualizações { #body-updates }
## Atualização substituindo com `PUT` { #update-replacing-with-put }
## Atualização de dados existentes com `PUT` { #update-replacing-with-put }
Para atualizar um item, você pode usar a operação <a href="https://developer.mozilla.org/en-US/docs/Web/HTTP/Methods/PUT" class="external-link" target="_blank">HTTP `PUT`</a>.
@@ -22,13 +22,13 @@ Isso significa que, se você quiser atualizar o item `bar` usando `PUT` com um c
}
```
como ele não inclui o atributo já armazenado `"tax": 20.2`, o modelo de entrada assumiria o valor padrão de `"tax": 10.5`.
Como ele não inclui o atributo já armazenado `"tax": 20.2`, o modelo de entrada assumiria o valor padrão de `"tax": 10.5`.
E os dados seriam salvos com esse "novo" `tax` de `10.5`.
## Atualizações parciais com `PATCH` { #partial-updates-with-patch }
Você também pode usar a operação <a href="https://developer.mozilla.org/en-US/docs/Web/HTTP/Methods/PATCH" class="external-link" target="_blank">HTTP `PATCH`</a> para atualizar dados *parcialmente*.
Você também pode usar a operação <a href="https://developer.mozilla.org/en-US/docs/Web/HTTP/Methods/PATCH" class="external-link" target="_blank">HTTP `PATCH`</a> para atualizar parcialmente os dados.
Isso significa que você pode enviar apenas os dados que deseja atualizar, deixando o restante intacto.
@@ -40,17 +40,25 @@ E muitas equipes usam apenas `PUT`, mesmo para atualizações parciais.
Você é **livre** para usá-los como preferir, **FastAPI** não impõe restrições.
Mas este guia mostra, mais ou menos, como eles são destinados a serem usados.
Mas este guia te dá uma ideia de como eles são destinados a serem usados.
///
### Usando o parâmetro `exclude_unset` do Pydantic { #using-pydantics-exclude-unset-parameter }
Se você quiser receber atualizações parciais, é muito útil usar o parâmetro `exclude_unset` no `.model_dump()` do modelo do Pydantic.
Se você quiser receber atualizações parciais, é muito útil usar o parâmetro `exclude_unset` no método `.model_dump()` do modelo do Pydantic.
Como `item.model_dump(exclude_unset=True)`.
Isso geraria um `dict` com apenas os dados que foram definidos ao criar o modelo `item`, excluindo os valores padrão.
/// info | Informação
No Pydantic v1, o método que era chamado `.dict()` e foi descontinuado (mas ainda suportado) no Pydantic v2. Agora, deve-se usar o método `.model_dump()`.
Os exemplos aqui usam `.dict()` para compatibilidade com o Pydantic v1, mas você deve usar `.model_dump()` a partir do Pydantic v2.
///
Isso gera um `dict` com apenas os dados definidos ao criar o modelo `item`, excluindo os valores padrão.
Então, você pode usar isso para gerar um `dict` com apenas os dados definidos (enviados na solicitação), omitindo valores padrão:
@@ -60,23 +68,31 @@ Então, você pode usar isso para gerar um `dict` com apenas os dados definidos
Agora, você pode criar uma cópia do modelo existente usando `.model_copy()`, e passar o parâmetro `update` com um `dict` contendo os dados para atualizar.
/// info | Informação
No Pydantic v1, o método era chamado `.copy()`, ele foi descontinuado (mas ainda suportado) no Pydantic v2, e renomeado para `.model_copy()`.
Os exemplos aqui usam `.copy()` para compatibilidade com o Pydantic v1, mas você deve usar `.model_copy()` com o Pydantic v2.
///
Como `stored_item_model.model_copy(update=update_data)`:
{* ../../docs_src/body_updates/tutorial002_py310.py hl[33] *}
### Recapitulando as atualizações parciais { #partial-updates-recap }
Resumindo, para aplicar atualizações parciais você deveria:
Resumindo, para aplicar atualizações parciais você pode:
* (Opcionalmente) usar `PATCH` em vez de `PUT`.
* Recuperar os dados armazenados.
* Colocar esses dados em um modelo do Pydantic.
* Gerar um `dict` sem valores padrão a partir do modelo de entrada (usando `exclude_unset`).
* Dessa forma, você pode atualizar apenas os valores realmente definidos pelo usuário, em vez de substituir valores já armazenados por valores padrão do modelo.
* Dessa forma, você pode atualizar apenas os valores definidos pelo usuário, em vez de substituir os valores já armazenados com valores padrão em seu modelo.
* Criar uma cópia do modelo armazenado, atualizando seus atributos com as atualizações parciais recebidas (usando o parâmetro `update`).
* Converter o modelo copiado em algo que possa ser armazenado no seu BD (por exemplo, usando o `jsonable_encoder`).
* Isso é comparável a usar o método `.model_dump()` do modelo novamente, mas garante (e converte) os valores para tipos de dados que possam ser convertidos em JSON, por exemplo, `datetime` para `str`.
* Salvar os dados no seu BD.
* Converter o modelo copiado em algo que possa ser armazenado no seu banco de dados (por exemplo, usando o `jsonable_encoder`).
* Isso é comparável ao uso do método `.model_dump()`, mas garante (e converte) os valores para tipos de dados que possam ser convertidos em JSON, por exemplo, `datetime` para `str`.
* Salvar os dados no seu banco de dados.
* Retornar o modelo atualizado.
{* ../../docs_src/body_updates/tutorial002_py310.py hl[28:35] *}
@@ -93,8 +109,8 @@ Mas o exemplo aqui usa `PATCH` porque foi criado para esses casos de uso.
Observe que o modelo de entrada ainda é validado.
Portanto, se você quiser receber atualizações parciais que possam omitir todos os atributos, você precisa ter um modelo com todos os atributos marcados como opcionais (com valores padrão ou `None`).
Portanto, se você quiser receber atualizações parciais que possam omitir todos os atributos, precisa ter um modelo com todos os atributos marcados como opcionais (com valores padrão ou `None`).
Para distinguir entre os modelos com todos os valores opcionais para **atualizações** e modelos com valores obrigatórios para **criação**, você pode usar as ideias descritas em [Modelos Adicionais](extra-models.md){.internal-link target=_blank}.
Para distinguir os modelos com todos os valores opcionais para **atualizações** e modelos com valores obrigatórios para **criação**, você pode usar as ideias descritas em [Modelos Adicionais](extra-models.md){.internal-link target=_blank}.
///

View File

@@ -10,11 +10,11 @@ Para declarar um corpo da **requisição**, você utiliza os modelos do <a href=
/// info | Informação
Para enviar dados, você deveria usar um dos: `POST` (o mais comum), `PUT`, `DELETE` ou `PATCH`.
Para enviar dados, você deve usar um dos: `POST` (o mais comum), `PUT`, `DELETE` ou `PATCH`.
Enviar um corpo em uma requisição `GET` não tem um comportamento definido nas especificações, porém é suportado pelo FastAPI, apenas para casos de uso bem complexos/extremos.
Como é desencorajado, a documentação interativa com Swagger UI não irá mostrar a documentação para o corpo da requisição ao usar `GET`, e proxies intermediários podem não suportá-lo.
Como é desencorajado, a documentação interativa com Swagger UI não irá mostrar a documentação para o corpo da requisição para um `GET`, e proxies que intermediarem podem não suportar o corpo da requisição.
///
@@ -32,8 +32,7 @@ Utilize os tipos Python padrão para todos os atributos:
{* ../../docs_src/body/tutorial001_py310.py hl[5:9] *}
Assim como quando declaramos parâmetros de consulta, quando um atributo do modelo possui um valor padrão, ele não é obrigatório. Caso contrário, é obrigatório. Use `None` para torná-lo apenas opcional.
Assim como quando declaramos parâmetros de consulta, quando um atributo do modelo possui um valor padrão, ele se torna opcional. Caso contrário, se torna obrigatório. Use `None` para torná-lo opcional.
Por exemplo, o modelo acima declara um JSON "`object`" (ou `dict` no Python) como esse:
@@ -67,7 +66,7 @@ Para adicioná-lo à sua *operação de rota*, declare-o da mesma maneira que vo
Apenas com essa declaração de tipos do Python, o **FastAPI** irá:
* Ler o corpo da requisição como JSON.
* Ler o corpo da requisição como um JSON.
* Converter os tipos correspondentes (se necessário).
* Validar os dados.
* Se algum dado for inválido, irá retornar um erro bem claro, indicando exatamente onde e o que estava incorreto.
@@ -128,6 +127,14 @@ Dentro da função, você pode acessar todos os atributos do objeto do modelo di
{* ../../docs_src/body/tutorial002_py310.py *}
/// info | Informação
No Pydantic v1 o método se chamava `.dict()`, ele foi descontinuado (mas ainda é suportado) no Pydantic v2, e renomeado para `.model_dump()`.
Os exemplos aqui usam `.dict()` para compatibilidade com o Pydantic v1, mas você deve usar `.model_dump()` se puder usar o Pydantic v2.
///
## Corpo da requisição + parâmetros de rota { #request-body-path-parameters }
Você pode declarar parâmetros de rota e corpo da requisição ao mesmo tempo.
@@ -136,7 +143,6 @@ O **FastAPI** irá reconhecer que os parâmetros da função que combinam com pa
{* ../../docs_src/body/tutorial003_py310.py hl[15:16] *}
## Corpo da requisição + parâmetros de rota + parâmetros de consulta { #request-body-path-query-parameters }
Você também pode declarar parâmetros de **corpo**, **rota** e **consulta**, ao mesmo tempo.

View File

@@ -22,13 +22,21 @@ Aqui está uma ideia geral de como os modelos poderiam parecer com seus campos d
{* ../../docs_src/extra_models/tutorial001_py310.py hl[7,9,14,20,22,27:28,31:33,38:39] *}
### Sobre `**user_in.model_dump()` { #about-user-in-model-dump }
/// info | Informação
#### O `.model_dump()` do Pydantic { #pydantics-model-dump }
No Pydantic v1 o método se chamava `.dict()`, ele foi descontinuado (mas ainda é suportado) no Pydantic v2 e renomeado para `.model_dump()`.
Os exemplos aqui usam `.dict()` por compatibilidade com o Pydantic v1, mas você deve usar `.model_dump()` se puder usar o Pydantic v2.
///
### Sobre `**user_in.dict()` { #about-user-in-dict }
#### O `.dict()` do Pydantic { #pydantics-dict }
`user_in` é um modelo Pydantic da classe `UserIn`.
Os modelos Pydantic possuem um método `.model_dump()` que retorna um `dict` com os dados do modelo.
Os modelos Pydantic possuem um método `.dict()` que retorna um `dict` com os dados do modelo.
Então, se criarmos um objeto Pydantic `user_in` como:
@@ -39,7 +47,7 @@ user_in = UserIn(username="john", password="secret", email="john.doe@example.com
e depois chamarmos:
```Python
user_dict = user_in.model_dump()
user_dict = user_in.dict()
```
agora temos um `dict` com os dados na variável `user_dict` (é um `dict` em vez de um objeto de modelo Pydantic).
@@ -95,20 +103,20 @@ UserInDB(
#### Um modelo Pydantic a partir do conteúdo de outro { #a-pydantic-model-from-the-contents-of-another }
Como no exemplo acima, obtivemos o `user_dict` a partir do `user_in.model_dump()`, este código:
Como no exemplo acima, obtivemos o `user_dict` a partir do `user_in.dict()`, este código:
```Python
user_dict = user_in.model_dump()
user_dict = user_in.dict()
UserInDB(**user_dict)
```
seria equivalente a:
```Python
UserInDB(**user_in.model_dump())
UserInDB(**user_in.dict())
```
...porque `user_in.model_dump()` é um `dict`, e depois fazemos o Python "desembrulhá-lo" passando-o para `UserInDB` precedido por `**`.
...porque `user_in.dict()` é um `dict`, e depois fazemos o Python "desembrulhá-lo" passando-o para `UserInDB` precedido por `**`.
Então, obtemos um modelo Pydantic a partir dos dados em outro modelo Pydantic.
@@ -117,7 +125,7 @@ Então, obtemos um modelo Pydantic a partir dos dados em outro modelo Pydantic.
E, então, adicionando o argumento de palavra-chave extra `hashed_password=hashed_password`, como em:
```Python
UserInDB(**user_in.model_dump(), hashed_password=hashed_password)
UserInDB(**user_in.dict(), hashed_password=hashed_password)
```
...acaba sendo como:

View File

@@ -33,7 +33,7 @@ Para isso, primeiro importe:
O FastAPI adicionou suporte a `Annotated` (e passou a recomendá-lo) na versão 0.95.0.
Se você tiver uma versão mais antiga, teria erros ao tentar usar `Annotated`.
Se você tiver uma versão mais antiga, terá erros ao tentar usar `Annotated`.
Certifique-se de [Atualizar a versão do FastAPI](../deployment/versions.md#upgrading-the-fastapi-versions){.internal-link target=_blank} para pelo menos 0.95.1 antes de usar `Annotated`.
@@ -109,7 +109,7 @@ Agora o FastAPI vai:
## Alternativa (antiga): `Query` como valor padrão { #alternative-old-query-as-the-default-value }
Versões anteriores do FastAPI (antes de <abbr title="before 2023-03 - antes de 2023-03">0.95.0</abbr>) exigiam que você usasse `Query` como valor padrão do seu parâmetro, em vez de colocá-lo em `Annotated`, há uma grande chance de você ver código usando isso por aí, então vou explicar.
Versões anteriores do FastAPI (antes de <abbr title="antes de 2023-03">0.95.0</abbr>) exigiam que você usasse `Query` como valor padrão do seu parâmetro, em vez de colocá-lo em `Annotated`. É muito provável que você veja código assim por aí, então vou te explicar.
/// tip | Dica
@@ -192,7 +192,7 @@ Você também pode adicionar um parâmetro `min_length`:
## Adicione expressões regulares { #add-regular-expressions }
Você pode definir um `pattern` de <abbr title="A regular expression, regex or regexp is a sequence of characters that define a search pattern for strings. - Uma expressão regular, regex ou regexp é uma sequência de caracteres que define um padrão de busca para strings.">expressão regular</abbr> que o parâmetro deve corresponder:
Você pode definir um `pattern` de <abbr title="Uma expressão regular, regex ou regexp é uma sequência de caracteres que define um padrão de busca para strings.">expressão regular</abbr> que o parâmetro deve corresponder:
{* ../../docs_src/query_params_str_validations/tutorial004_an_py310.py hl[11] *}
@@ -206,6 +206,20 @@ Se você se sentir perdido com essas ideias de **"expressão regular"**, não se
Agora você sabe que, sempre que precisar delas, pode usá-las no **FastAPI**.
### Pydantic v1 `regex` em vez de `pattern` { #pydantic-v1-regex-instead-of-pattern }
Antes da versão 2 do Pydantic e antes do FastAPI 0.100.0, o parâmetro se chamava `regex` em vez de `pattern`, mas agora está descontinuado.
Você ainda pode ver algum código usando isso:
//// tab | Pydantic v1
{* ../../docs_src/query_params_str_validations/tutorial004_regex_an_py310.py hl[11] *}
////
Mas saiba que isso está descontinuado e deve ser atualizado para usar o novo parâmetro `pattern`. 🤓
## Valores padrão { #default-values }
Você pode, claro, usar valores padrão diferentes de `None`.
@@ -266,7 +280,7 @@ Então, com uma URL como:
http://localhost:8000/items/?q=foo&q=bar
```
você receberia os múltiplos valores dos *parâmetros de consulta* `q` (`foo` e `bar`) em uma `list` Python dentro da sua *função de operação de rota*, no *parâmetro da função* `q`.
você receberá os múltiplos valores do *parâmetro de consulta* `q` (`foo` e `bar`) em uma `list` Python dentro da sua *função de operação de rota*, no *parâmetro da função* `q`.
Assim, a resposta para essa URL seria:
@@ -336,7 +350,7 @@ Essas informações serão incluídas no OpenAPI gerado e usadas pelas interface
Tenha em mente que ferramentas diferentes podem ter níveis diferentes de suporte ao OpenAPI.
Algumas delas podem ainda não mostrar todas as informações extras declaradas, embora na maioria dos casos a funcionalidade ausente já esteja planejada para desenvolvimento.
Algumas delas podem ainda não mostrar todas as informações extras declaradas, embora na maioria dos casos o recurso ausente já esteja planejado para desenvolvimento.
///
@@ -372,7 +386,7 @@ Então você pode declarar um `alias`, e esse alias será usado para encontrar o
Agora digamos que você não gosta mais desse parâmetro.
Você tem que deixá-lo por um tempo, pois há clientes usando-o, mas quer que a documentação mostre claramente que ele está <abbr title="obsolete, recommended not to use it - obsoleto, recomenda-se não usá-lo">deprecated</abbr>.
Você tem que deixá-lo por um tempo, pois há clientes usando-o, mas quer que a documentação mostre claramente que ele está <abbr title="obsoleto, recomenda-se não usá-lo">descontinuado</abbr>.
Então passe o parâmetro `deprecated=True` para `Query`:
@@ -402,7 +416,7 @@ O Pydantic também tem <a href="https://docs.pydantic.dev/latest/concepts/valida
///
Por exemplo, este validador personalizado verifica se o ID do item começa com `isbn-` para um número de livro <abbr title="ISBN means International Standard Book Number - ISBN significa Número Padrão Internacional de Livro">ISBN</abbr> ou com `imdb-` para um ID de URL de filme <abbr title="IMDB (Internet Movie Database) is a website with information about movies - IMDB (Internet Movie Database) é um site com informações sobre filmes">IMDB</abbr>:
Por exemplo, este validador personalizado verifica se o ID do item começa com `isbn-` para um número de livro <abbr title="ISBN significa Número Padrão Internacional de Livro">ISBN</abbr> ou com `imdb-` para um ID de URL de filme <abbr title="IMDB (Internet Movie Database) é um site com informações sobre filmes">IMDB</abbr>:
{* ../../docs_src/query_params_str_validations/tutorial015_an_py310.py hl[5,16:19,24] *}
@@ -414,7 +428,7 @@ Isso está disponível com a versão 2 do Pydantic ou superior. 😎
/// tip | Dica
Se você precisar fazer qualquer tipo de validação que exija comunicação com algum **componente externo**, como um banco de dados ou outra API, você deveria usar **Dependências do FastAPI** em vez disso; você aprenderá sobre elas mais adiante.
Se você precisar fazer qualquer tipo de validação que exija comunicação com algum **componente externo**, como um banco de dados ou outra API, você deve usar **Dependências do FastAPI** em vez disso; você aprenderá sobre elas mais adiante.
Esses validadores personalizados são para coisas que podem ser verificadas **apenas** com os **mesmos dados** fornecidos na requisição.
@@ -426,7 +440,7 @@ O ponto importante é apenas usar **`AfterValidator` com uma função dentro de
---
Mas se você estiver curioso sobre este exemplo de código específico e ainda entretido, aqui vão alguns detalhes extras.
Mas se você está curioso sobre este exemplo específico e ainda entretido, aqui vão alguns detalhes extras.
#### String com `value.startswith()` { #string-with-value-startswith }
@@ -436,7 +450,7 @@ Percebeu? Uma string usando `value.startswith()` pode receber uma tupla, e verif
#### Um item aleatório { #a-random-item }
Com `data.items()` obtemos um <abbr title="Something we can iterate on with a for loop, like a list, set, etc. - Algo que podemos iterar com um laço for, como uma list, set, etc.">objeto iterável</abbr> com tuplas contendo a chave e o valor de cada item do dicionário.
Com `data.items()` obtemos um <abbr title="Algo que podemos iterar com um laço for, como uma list, set, etc.">objeto iterável</abbr> com tuplas contendo a chave e o valor de cada item do dicionário.
Convertimos esse objeto iterável em uma `list` adequada com `list(data.items())`.

View File

@@ -252,6 +252,20 @@ Então, se você enviar uma solicitação para essa *operação de rota* para o
/// info | Informação
No Pydantic v1, o método era chamado `.dict()`, ele foi descontinuado (mas ainda suportado) no Pydantic v2 e renomeado para `.model_dump()`.
Os exemplos aqui usam `.dict()` para compatibilidade com Pydantic v1, mas você deve usar `.model_dump()` em vez disso se puder usar Pydantic v2.
///
/// info | Informação
O FastAPI usa `.dict()` do modelo Pydantic com <a href="https://docs.pydantic.dev/1.10/usage/exporting_models/#modeldict" class="external-link" target="_blank">seu parâmetro `exclude_unset`</a> para chegar a isso.
///
/// info | Informação
Você também pode usar:
* `response_model_exclude_defaults=True`

View File

@@ -8,17 +8,39 @@ Aqui estão várias maneiras de fazer isso.
Você pode declarar `examples` para um modelo Pydantic que serão adicionados ao JSON Schema gerado.
//// tab | Pydantic v2
{* ../../docs_src/schema_extra_example/tutorial001_py310.py hl[13:24] *}
////
//// tab | Pydantic v1
{* ../../docs_src/schema_extra_example/tutorial001_pv1_py310.py hl[13:23] *}
////
Essas informações extras serão adicionadas como estão ao **JSON Schema** de saída para esse modelo e serão usadas na documentação da API.
Você pode usar o atributo `model_config`, que recebe um `dict`, conforme descrito na <a href="https://docs.pydantic.dev/latest/api/config/" class="external-link" target="_blank">documentação do Pydantic: Configuration</a>.
//// tab | Pydantic v2
Na versão 2 do Pydantic, você usaria o atributo `model_config`, que recebe um `dict`, conforme descrito na <a href="https://docs.pydantic.dev/latest/api/config/" class="external-link" target="_blank">documentação do Pydantic: Configuration</a>.
Você pode definir `"json_schema_extra"` com um `dict` contendo quaisquer dados adicionais que você queira que apareçam no JSON Schema gerado, incluindo `examples`.
////
//// tab | Pydantic v1
Na versão 1 do Pydantic, você usaria uma classe interna `Config` e `schema_extra`, conforme descrito na <a href="https://docs.pydantic.dev/1.10/usage/schema/#schema-customization" class="external-link" target="_blank">documentação do Pydantic: Schema customization</a>.
Você pode definir `schema_extra` com um `dict` contendo quaisquer dados adicionais que você queira que apareçam no JSON Schema gerado, incluindo `examples`.
////
/// tip | Dica
Você poderia usar a mesma técnica para estender o JSON Schema e adicionar suas próprias informações extras personalizadas.
Você pode usar a mesma técnica para estender o JSON Schema e adicionar suas próprias informações extras personalizadas.
Por exemplo, você poderia usá-la para adicionar metadados para uma interface de usuário de front-end, etc.
@@ -28,7 +50,7 @@ Por exemplo, você poderia usá-la para adicionar metadados para uma interface d
O OpenAPI 3.1.0 (usado desde o FastAPI 0.99.0) adicionou suporte a `examples`, que faz parte do padrão **JSON Schema**.
Antes disso, ele suportava apenas a palavrachave `example` com um único exemplo. Isso ainda é suportado pelo OpenAPI 3.1.0, mas é descontinuado e não faz parte do padrão JSON Schema. Portanto, você é incentivado a migrar de `example` para `examples`. 🤓
Antes disso, ele suportava apenas a palavrachave `example` com um único exemplo. Isso ainda é suportado pelo OpenAPI 3.1.0, mas é descontinuado e não faz parte do padrão JSON Schema. Portanto, é recomendado migrar de `example` para `examples`. 🤓
Você pode ler mais no final desta página.
@@ -80,7 +102,7 @@ No entanto, <abbr title="2023-08-26">no momento em que isto foi escrito</abbr>,
Antes do **JSON Schema** suportar `examples`, o OpenAPI já tinha suporte para um campo diferente também chamado `examples`.
Esse `examples` **específico do OpenAPI** vai em outra seção da especificação OpenAPI. Ele fica nos **detalhes de cada *operação de rota***, não dentro de cada JSON Schema.
Esse `examples` específico do OpenAPI vai em outra seção da especificação. Ele fica nos **detalhes de cada função de operação de rota**, não dentro de cada JSON Schema.
E o Swagger UI tem suportado esse campo `examples` particular há algum tempo. Então, você pode usá-lo para **mostrar** diferentes **exemplos na UI da documentação**.
@@ -167,9 +189,9 @@ Depois, o JSON Schema adicionou um campo <a href="https://json-schema.org/draft/
E então o novo OpenAPI 3.1.0 passou a se basear na versão mais recente (JSON Schema 2020-12), que incluiu esse novo campo `examples`.
E agora esse novo campo `examples` tem precedência sobre o antigo campo único (e customizado) `example`, que agora está descontinuado.
Agora, esse novo campo `examples` tem precedência sobre o antigo (e customizado) campo único `example`, que agora está descontinuado.
Esse novo campo `examples` no JSON Schema é **apenas uma `list`** de exemplos, não um dict com metadados extras como nos outros lugares do OpenAPI (descritos acima).
Esse novo campo `examples` no JSON Schema é **apenas uma `list`** de exemplos, não um `dict` com metadados extras como nos outros lugares do OpenAPI (descritos acima).
/// info | Informação
@@ -191,7 +213,7 @@ Mas agora que o FastAPI 0.99.0 e superiores usam o OpenAPI 3.1.0, que usa o JSON
### Swagger UI e `examples` específicos do OpenAPI { #swagger-ui-and-openapi-specific-examples }
Agora, como o Swagger UI não suportava vários exemplos no JSON Schema (em 2023-08-26), os usuários não tinham uma forma de mostrar vários exemplos na documentação.
Como o Swagger UI não suportava vários exemplos no JSON Schema (em 2023-08-26), os usuários não tinham uma forma de mostrar vários exemplos na documentação.
Para resolver isso, o FastAPI `0.103.0` **adicionou suporte** para declarar o mesmo antigo campo **específico do OpenAPI** `examples` com o novo parâmetro `openapi_examples`. 🤓

View File

@@ -1,8 +1,8 @@
# Тестовый файл LLM { #llm-test-file }
Этот документ проверяет, понимает ли <abbr title="Large Language Model - Большая языковая модель">LLM</abbr>, переводящая документацию, `general_prompt` в `scripts/translate.py` и языковой специфичный промпт в `docs/{language code}/llm-prompt.md`. Языковой специфичный промпт добавляется к `general_prompt`.
Этот документ проверяет, понимает ли <abbr title="Large Language Model Большая языковая модель">LLM</abbr>, переводящая документацию, `general_prompt` в `scripts/translate.py` и языковой специфичный промпт в `docs/{language code}/llm-prompt.md`. Языковой специфичный промпт добавляется к `general_prompt`.
Тесты, добавленные здесь, увидят все создатели языковых специфичных промптов.
Тесты, добавленные здесь, увидят все создатели языковых промптов.
Использование:
@@ -11,7 +11,7 @@
* Проверьте, всё ли в порядке в переводе.
* При необходимости улучшите ваш языковой специфичный промпт, общий промпт или английский документ.
* Затем вручную исправьте оставшиеся проблемы в переводе, чтобы он был хорошим.
* Переведите заново, имея хороший перевод на месте. Идеальным результатом будет ситуация, когда LLM больше не вносит изменений в перевод. Это означает, что общий промпт и ваш языковой специфичный промпт настолько хороши, насколько это возможно (иногда он будет делать несколько, казалось бы, случайных изменений, причина в том, что <a href="https://doublespeak.chat/#/handbook#deterministic-output" class="external-link" target="_blank">LLM — недетерминированные алгоритмы</a>).
* Переведите заново, имея хороший перевод на месте. Идеальным результатом будет ситуация, когда LLM больше не вносит изменений в перевод. Это означает, что общий промпт и ваш языковой специфичный промпт максимально хороши (иногда он будет делать несколько, казалось бы, случайных изменений, причина в том, что <a href="https://doublespeak.chat/#/handbook#deterministic-output" class="external-link" target="_blank">LLM — недетерминированные алгоритмы</a>).
Тесты:
@@ -197,10 +197,10 @@ works(foo="bar") # Это работает 🎉
### abbr даёт полную расшифровку { #the-abbr-gives-a-full-phrase }
* <abbr title="Getting Things Done - Как привести дела в порядок">GTD</abbr>
* <abbr title="less than - меньше чем"><code>lt</code></abbr>
* <abbr title="XML Web Token - XML веб‑токен">XWT</abbr>
* <abbr title="Parallel Server Gateway Interface - Параллельный серверный интерфейс шлюза">PSGI</abbr>
* <abbr title="Getting Things Done Как привести дела в порядок">GTD</abbr>
* <abbr title="less than меньше чем"><code>lt</code></abbr>
* <abbr title="XML Web Token XML веб‑токен">XWT</abbr>
* <abbr title="Parallel Server Gateway Interface Параллельный серверный интерфейс шлюза">PSGI</abbr>
### abbr даёт объяснение { #the-abbr-gives-an-explanation }
@@ -209,8 +209,8 @@ works(foo="bar") # Это работает 🎉
### abbr даёт полную расшифровку и объяснение { #the-abbr-gives-a-full-phrase-and-an-explanation }
* <abbr title="Mozilla Developer Network - Сеть разработчиков Mozilla: документация для разработчиков, созданная командой Firefox">MDN</abbr>
* <abbr title="Input/Output - Ввод/Вывод: чтение или запись на диск, сетевое взаимодействие.">I/O</abbr>.
* <abbr title="Mozilla Developer Network Сеть разработчиков Mozilla: документация для разработчиков, созданная командой Firefox">MDN</abbr>
* <abbr title="Input/Output Ввод/Вывод: чтение или запись на диск, сетевое взаимодействие.">I/O</abbr>.
////

View File

@@ -14,7 +14,7 @@
{* ../../docs_src/path_operation_advanced_configuration/tutorial001_py39.py hl[6] *}
### Использование имени *функции-обработчика пути* как operationId { #using-the-path-operation-function-name-as-the-operationid }
### Использование имени функции-обработчика пути как operationId { #using-the-path-operation-function-name-as-the-operationid }
Если вы хотите использовать имена функций ваших API в качестве `operationId`, вы можете пройти по всем из них и переопределить `operation_id` каждой *операции пути* с помощью их `APIRoute.name`.
@@ -38,7 +38,7 @@
## Исключить из OpenAPI { #exclude-from-openapi }
Чтобы исключить *операцию пути* из генерируемой схемы OpenAPI (а значит, и из автоматических систем документации), используйте параметр `include_in_schema` и установите его в `False`:
Чтобы исключить *операцию пути* из генерируемой схемы OpenAPI (а значит, и из автоматической документации), используйте параметр `include_in_schema` и установите его в `False`:
{* ../../docs_src/path_operation_advanced_configuration/tutorial003_py39.py hl[6] *}
@@ -48,7 +48,7 @@
Добавление `\f` (экранированного символа «form feed») заставит **FastAPI** обрезать текст, используемый для OpenAPI, в этой точке.
Это не отобразится в документации, но другие инструменты (например, Sphinx) смогут использовать остальное.
Эта часть не попадёт в документацию, но другие инструменты (например, Sphinx) смогут использовать остальное.
{* ../../docs_src/path_operation_advanced_configuration/tutorial004_py310.py hl[17:27] *}
@@ -56,7 +56,7 @@
Вы, вероятно, уже видели, как объявлять `response_model` и `status_code` для *операции пути*.
Это определяет метаданные об основном HTTP-ответе *операции пути*.
Это определяет метаданные об основном ответе *операции пути*.
Также можно объявлять дополнительные ответы с их моделями, статус-кодами и т.д.
@@ -76,7 +76,7 @@
Там есть `tags`, `parameters`, `requestBody`, `responses` и т.д.
Эта специфичная для *операции пути* схема OpenAPI обычно генерируется автоматически **FastAPI**, но вы также можете её расширить.
Эта спецификация OpenAPI, специфичная для *операции пути*, обычно генерируется автоматически **FastAPI**, но вы также можете её расширить.
/// tip | Совет
@@ -129,13 +129,13 @@
}
```
### Пользовательская схема OpenAPI для *операции пути* { #custom-openapi-path-operation-schema }
### Пользовательская схема OpenAPI для операции пути { #custom-openapi-path-operation-schema }
Словарь в `openapi_extra` будет глубоко объединён с автоматически сгенерированной схемой OpenAPI для *операции пути*.
Словарь в `openapi_extra` будет объединён с автоматически сгенерированной схемой OpenAPI для *операции пути*.
Таким образом, вы можете добавить дополнительные данные к автоматически сгенерированной схеме.
Например, вы можете решить читать и валидировать HTTP-запрос своим кодом, не используя автоматические возможности FastAPI и Pydantic, но при этом захотите описать HTTP-запрос в схеме OpenAPI.
Например, вы можете решить читать и валидировать запрос своим кодом, не используя автоматические возможности FastAPI и Pydantic, но при этом захотите описать запрос в схеме OpenAPI.
Это можно сделать с помощью `openapi_extra`:
@@ -149,20 +149,52 @@
Используя тот же приём, вы можете воспользоваться Pydantic-моделью, чтобы определить JSON Schema, которая затем будет включена в пользовательский раздел схемы OpenAPI для *операции пути*.
И вы можете сделать это, даже если тип данных в HTTP-запросе — не JSON.
И вы можете сделать это, даже если тип данных в запросе — не JSON.
Например, в этом приложении мы не используем встроенную функциональность FastAPI для извлечения JSON Schema из моделей Pydantic, равно как и автоматическую валидацию JSON. Мы объявляем тип содержимого HTTP-запроса как YAML, а не JSON:
Например, в этом приложении мы не используем встроенную функциональность FastAPI для извлечения JSON Schema из моделей Pydantic, равно как и автоматическую валидацию JSON. Мы объявляем тип содержимого запроса как YAML, а не JSON:
//// tab | Pydantic v2
{* ../../docs_src/path_operation_advanced_configuration/tutorial007_py39.py hl[15:20, 22] *}
////
//// tab | Pydantic v1
{* ../../docs_src/path_operation_advanced_configuration/tutorial007_pv1_py39.py hl[15:20, 22] *}
////
/// info | Информация
В Pydantic версии 1 метод для получения JSON Schema модели назывался `Item.schema()`, в Pydantic версии 2 метод называется `Item.model_json_schema()`.
///
Тем не менее, хотя мы не используем встроенную функциональность по умолчанию, мы всё равно используем Pydantic-модель, чтобы вручную сгенерировать JSON Schema для данных, которые мы хотим получить в YAML.
Затем мы работаем с HTTP-запросом напрямую и извлекаем тело как `bytes`. Это означает, что FastAPI даже не попытается распарсить полезную нагрузку HTTP-запроса как JSON.
Затем мы работаем с запросом напрямую и извлекаем тело как `bytes`. Это означает, что FastAPI даже не попытается распарсить полезную нагрузку запроса как JSON.
А затем в нашем коде мы напрямую парсим это содержимое YAML и снова используем ту же Pydantic-модель, чтобы валидировать YAML-содержимое:
А затем в нашем коде мы напрямую парсим этот YAML и снова используем ту же Pydantic-модель для валидации YAML-содержимого:
//// tab | Pydantic v2
{* ../../docs_src/path_operation_advanced_configuration/tutorial007_py39.py hl[24:31] *}
////
//// tab | Pydantic v1
{* ../../docs_src/path_operation_advanced_configuration/tutorial007_pv1_py39.py hl[24:31] *}
////
/// info | Информация
В Pydantic версии 1 метод для парсинга и валидации объекта назывался `Item.parse_obj()`, в Pydantic версии 2 метод называется `Item.model_validate()`.
///
/// tip | Совет
Здесь мы переиспользуем ту же Pydantic-модель.

View File

@@ -46,6 +46,12 @@ $ pip install "fastapi[all]"
</div>
/// info | Информация
В Pydantic v1 он входил в основной пакет. Теперь он распространяется как отдельный пакет, чтобы вы могли установить его только при необходимости.
///
### Создание объекта `Settings` { #create-the-settings-object }
Импортируйте `BaseSettings` из Pydantic и создайте подкласс, очень похожий на Pydanticмодель.
@@ -54,8 +60,24 @@ $ pip install "fastapi[all]"
Вы можете использовать все те же возможности валидации и инструменты, что и для Pydanticмоделей, например разные типы данных и дополнительную валидацию через `Field()`.
//// tab | Pydantic v2
{* ../../docs_src/settings/tutorial001_py39.py hl[2,5:8,11] *}
////
//// tab | Pydantic v1
/// info | Информация
В Pydantic v1 вы бы импортировали `BaseSettings` напрямую из `pydantic`, а не из `pydantic_settings`.
///
{* ../../docs_src/settings/tutorial001_pv1_py39.py hl[2,5:8,11] *}
////
/// tip | Совет
Если вам нужно что-то быстро скопировать и вставить, не используйте этот пример — воспользуйтесь последним ниже.
@@ -193,6 +215,8 @@ APP_NAME="ChimichangApp"
Затем обновите ваш `config.py` так:
//// tab | Pydantic v2
{* ../../docs_src/settings/app03_an_py39/config.py hl[9] *}
/// tip | Совет
@@ -201,6 +225,26 @@ APP_NAME="ChimichangApp"
///
////
//// tab | Pydantic v1
{* ../../docs_src/settings/app03_an_py39/config_pv1.py hl[9:10] *}
/// tip | Совет
Класс `Config` используется только для конфигурации Pydantic. Подробнее см. <a href="https://docs.pydantic.dev/1.10/usage/model_config/" class="external-link" target="_blank">Pydantic Model Config</a>.
///
////
/// info | Информация
В Pydantic версии 1 конфигурация задавалась во внутреннем классе `Config`, в Pydantic версии 2 — в атрибуте `model_config`. Этот атрибут принимает `dict`, и чтобы получить автозавершение и ошибки «на лету», вы можете импортировать и использовать `SettingsConfigDict` для описания этого `dict`.
///
Здесь мы задаем параметр конфигурации `env_file` внутри вашего класса Pydantic `Settings` и устанавливаем значение равным имени файла dotenv, который хотим использовать.
### Создание `Settings` только один раз с помощью `lru_cache` { #creating-the-settings-only-once-with-lru-cache }

View File

@@ -2,23 +2,21 @@
Если у вас старое приложение FastAPI, возможно, вы используете Pydantic версии 1.
FastAPI версии 0.100.0 поддерживал либо Pydantic v1, либо v2. Он использовал ту версию, которая была установлена.
FastAPI поддерживает и Pydantic v1, и v2 начиная с версии 0.100.0.
FastAPI версии 0.119.0 добавил частичную поддержку Pydantic v1 изнутри Pydantic v2 (как `pydantic.v1`), чтобы упростить миграцию на v2.
Если у вас был установлен Pydantic v2, использовался он. Если вместо этого был установлен Pydantic v1 — использовался он.
FastAPI 0.126.0 убрал поддержку Pydantic v1, при этом ещё некоторое время продолжал поддерживать `pydantic.v1`.
Сейчас Pydantic v1 объявлен устаревшим, и поддержка его будет удалена в следующих версиях FastAPI, поэтому вам следует **перейти на Pydantic v2**. Так вы получите последние возможности, улучшения и исправления.
/// warning | Предупреждение
Команда Pydantic прекратила поддержку Pydantic v1 для последних версий Python, начиная с **Python 3.14**.
Это включает `pydantic.v1`, который больше не поддерживается в Python 3.14 и выше.
Кроме того, команда Pydantic прекратила поддержку Pydantic v1 для последних версий Python, начиная с **Python 3.14**.
Если вы хотите использовать последние возможности Python, вам нужно убедиться, что вы используете Pydantic v2.
///
Если у вас старое приложение FastAPI с Pydantic v1, здесь я покажу, как мигрировать на Pydantic v2, и **возможности FastAPI 0.119.0**, которые помогут выполнить постепенную миграцию.
Если у вас старое приложение FastAPI с Pydantic v1, здесь я покажу, как мигрировать на Pydantic v2, и **новые возможности в FastAPI 0.119.0**, которые помогут выполнить постепенную миграцию.
## Официальное руководство { #official-guide }
@@ -40,13 +38,13 @@ FastAPI 0.126.0 убрал поддержку Pydantic v1, при этом ещ
Вы можете использовать <a href="https://github.com/pydantic/bump-pydantic" class="external-link" target="_blank">`bump-pydantic`</a> от той же команды Pydantic.
Этот инструмент поможет автоматически изменить большую часть кода, который нужно изменить.
Этот инструмент поможет автоматически внести большую часть необходимых изменений в код.
После этого вы можете запустить тесты и проверить, что всё работает. Если да — на этом всё. 😎
После этого запустите тесты и проверьте, что всё работает. Если да — на этом всё. 😎
## Pydantic v1 в v2 { #pydantic-v1-in-v2 }
Pydantic v2 включает всё из Pydantic v1 как подмодуль `pydantic.v1`. Но это больше не поддерживается в версиях Python выше 3.13.
Pydantic v2 включает всё из Pydantic v1 как подмодуль `pydantic.v1`.
Это означает, что вы можете установить последнюю версию Pydantic v2 и импортировать и использовать старые компоненты Pydantic v1 из этого подмодуля так, как если бы у вас был установлен старый Pydantic v1.
@@ -54,7 +52,7 @@ Pydantic v2 включает всё из Pydantic v1 как подмодуль `
### Поддержка FastAPI для Pydantic v1 внутри v2 { #fastapi-support-for-pydantic-v1-in-v2 }
Начиная с FastAPI 0.119.0, есть также частичная поддержка Pydantic v1 изнутри Pydantic v2, чтобы упростить миграцию на v2.
Начиная с FastAPI 0.119.0, есть также частичная поддержка Pydantic v1 в составе Pydantic v2, чтобы упростить миграцию на v2.
Таким образом, вы можете обновить Pydantic до последней версии 2 и сменить импорты на подмодуль `pydantic.v1` — во многих случаях всё просто заработает.
@@ -108,7 +106,7 @@ graph TB
style V2Field fill:#f9fff3
```
В некоторых случаях можно использовать и модели Pydantic v1, и v2 в одной и той же **операции пути** (обработчике пути) вашего приложения FastAPI:
В некоторых случаях можно использовать и модели Pydantic v1, и v2 в одной и той же операции пути (обработчике пути) вашего приложения FastAPI:
{* ../../docs_src/pydantic_v1_in_v2/tutorial003_an_py310.py hl[2:3,6,12,21:22] *}
@@ -124,12 +122,12 @@ graph TB
/// tip | Совет
Сначала попробуйте `bump-pydantic`: если тесты проходят и всё работает, вы справились одной командой. ✨
Сначала попробуйте `bump-pydantic`. Если тесты проходят и всё работает, вы справились одной командой. ✨
///
Если `bump-pydantic` не подходит для вашего случая, вы можете использовать поддержку одновременной работы моделей Pydantic v1 и v2 в одном приложении, чтобы мигрировать на Pydantic v2 постепенно.
Сначала вы можете обновить Pydantic до последней 2-й версии и изменить импорты так, чтобы все ваши модели использовали `pydantic.v1`.
Сначала обновите Pydantic до последней 2-й версии и измените импорты так, чтобы все ваши модели использовали `pydantic.v1`.
Затем вы можете начать мигрировать ваши модели с Pydantic v1 на v2 группами, поэтапно. 🚶
Затем начните мигрировать ваши модели с Pydantic v1 на v2 группами, поэтапно. 🚶

View File

@@ -2,7 +2,7 @@
При использовании **Pydantic v2** сгенерированный OpenAPI становится чуть более точным и **корректным**, чем раньше. 😎
На самом деле, в некоторых случаях в OpenAPI будет даже **две JSON-схемы** для одной и той же Pydanticмодели: для входа и для выхода — в зависимости от наличия **значений по умолчанию**.
На самом деле, в некоторых случаях в OpenAPI будет даже **две JSON схемы** для одной и той же Pydanticмодели: для входа и для выхода — в зависимости от наличия **значений по умолчанию**.
Посмотрим, как это работает, и как это изменить при необходимости.
@@ -34,7 +34,7 @@
{* ../../docs_src/separate_openapi_schemas/tutorial001_py310.py hl[19] *}
…то, поскольку у `description` есть значение по умолчанию, если вы **ничего не вернёте** для этого поля, оно всё равно будет иметь это **значение по умолчанию**.
…то, поскольку у `description` есть значение по умолчанию, даже если вы **ничего не вернёте** для этого поля, оно всё равно будет иметь это **значение по умолчанию**.
### Модель для данных ответа { #model-for-output-response-data }
@@ -46,13 +46,13 @@
Это означает, что у него **всегда будет какое‑то значение**, просто иногда это значение может быть `None` (или `null` в JSON).
Это означает, что клиентам, использующим ваш API, не нужно проверять, существует ли это значение или нет: они могут **исходить из того, что поле всегда присутствует**, но в некоторых случаях оно будет иметь значение по умолчанию `None`.
Следовательно, клиентам, использующим ваш API, не нужно проверять наличие этого значения: они могут **исходить из того, что поле всегда присутствует**, а в некоторых случаях имеет значение по умолчанию `None`.
В OpenAPI это описывается тем, что поле помечается как **обязательное**, поскольку оно всегда присутствует.
Из‑за этого JSON Schema для модели может отличаться в зависимости от использования для **входа** или **выхода**:
* для **входа** `description` **не будет обязательным**
* для **входа** `description` не будет обязательным
* для **выхода** оно будет **обязательным** (и при этом может быть `None`, или, в терминах JSON, `null`)
### Выходная модель в документации { #model-for-output-in-docs }
@@ -81,9 +81,9 @@
Однако бывают случаи, когда вы хотите иметь **одну и ту же схему для входа и выхода**.
Главный сценарий — когда у вас уже есть сгенерированный клиентский код/SDK, и вы пока не хотите обновлять весь этот автогенерируемый клиентский код/SDK, вероятно, вы захотите сделать это в какой-то момент, но, возможно, не прямо сейчас.
Главный сценарий — когда у вас уже есть сгенерированный клиентский код/SDK, и вы пока не хотите обновлять весь этот автогенерируемый код/SDK (рано или поздно вы это сделаете, но не сейчас).
В таком случае вы можете отключить эту функциональность в **FastAPI** с помощью параметра `separate_input_output_schemas=False`.
В таком случае вы можете отключить эту функциональность в FastAPI с помощью параметра `separate_input_output_schemas=False`.
/// info | Информация
@@ -95,8 +95,10 @@
### Одна и та же схема для входной и выходной моделей в документации { #same-schema-for-input-and-output-models-in-docs }
И теперь для модели будет одна общая схема и для входа, и для выхода — только `Item`, и в ней `description` будет **не обязательным**:
Теперь для этой модели будет одна общая схема и для входа, и для выхода — только `Item`, и в ней `description` будет **не обязательным**:
<div class="screenshot">
<img src="/img/tutorial/separate-openapi-schemas/image05.png">
</div>
Это то же поведение, что и в Pydantic v1. 🤓

View File

@@ -5,10 +5,10 @@
</style>
<p align="center">
<a href="https://fastapi.tiangolo.com/ru"><img src="https://fastapi.tiangolo.com/img/logo-margin/logo-teal.png" alt="FastAPI"></a>
<a href="https://fastapi.tiangolo.com"><img src="https://fastapi.tiangolo.com/img/logo-margin/logo-teal.png" alt="FastAPI"></a>
</p>
<p align="center">
<em>Фреймворк FastAPI: высокая производительность, прост в изучении, позволяет быстро писать код, готов к продакшн</em>
<em>Фреймворк FastAPI: высокая производительность, прост в изучении, быстрый в разработке, готов к продакшн</em>
</p>
<p align="center">
<a href="https://github.com/fastapi/fastapi/actions?query=workflow%3ATest+event%3Apush+branch%3Amaster" target="_blank">
@@ -40,7 +40,7 @@ FastAPI — это современный, быстрый (высокопрои
* **Скорость**: Очень высокая производительность, на уровне **NodeJS** и **Go** (благодаря Starlette и Pydantic). [Один из самых быстрых доступных фреймворков Python](#performance).
* **Быстрота разработки**: Увеличьте скорость разработки фич примерно на 200300%. *
* **Меньше ошибок**: Сократите примерно на 40% количество ошибок, вызванных человеком (разработчиком). *
* **Интуитивность**: Отличная поддержка редактора кода. <abbr title="также известное как: автодополнение, автозавершение, IntelliSense">Автозавершение</abbr> везде. Меньше времени на отладку.
* **Интуитивность**: Отличная поддержка редактора кода. <abbr title="также известное как: автодополнение, IntelliSense">Автозавершение</abbr> везде. Меньше времени на отладку.
* **Простота**: Разработан так, чтобы его было легко использовать и осваивать. Меньше времени на чтение документации.
* **Краткость**: Минимизируйте дублирование кода. Несколько возможностей из каждого объявления параметров. Меньше ошибок.
* **Надежность**: Получите код, готовый к продакшн. С автоматической интерактивной документацией.
@@ -117,12 +117,6 @@ FastAPI — это современный, быстрый (высокопрои
---
## Мини-документальный фильм о FastAPI { #fastapi-mini-documentary }
В конце 2025 года вышел <a href="https://www.youtube.com/watch?v=mpR8ngthqiE" class="external-link" target="_blank">мини-документальный фильм о FastAPI</a>, вы можете посмотреть его онлайн:
<a href="https://www.youtube.com/watch?v=mpR8ngthqiE" target="_blank"><img src="https://fastapi.tiangolo.com/img/fastapi-documentary.jpg" alt="FastAPI Mini Documentary"></a>
## **Typer**, FastAPI для CLI { #typer-the-fastapi-of-clis }
<a href="https://typer.tiangolo.com" target="_blank"><img src="https://typer.tiangolo.com/img/logo-margin/logo-margin-vector.svg" style="width: 20%;"></a>
@@ -263,7 +257,7 @@ INFO: Application startup complete.
* Получает HTTP-запросы по _путям_ `/` и `/items/{item_id}`.
* Оба _пути_ используют `GET` <em>операции</em> (также известные как HTTP _методы_).
* _Путь_ `/items/{item_id}` имеет _path-параметр_ `item_id`, который должен быть `int`.
* _Путь_ `/items/{item_id}` имеет _параметр пути_ `item_id`, который должен быть `int`.
* _Путь_ `/items/{item_id}` имеет необязательный `str` _параметр запроса_ `q`.
### Интерактивная документация API { #interactive-api-docs }
@@ -284,9 +278,9 @@ INFO: Application startup complete.
## Пример обновления { #example-upgrade }
Теперь измените файл `main.py`, чтобы принимать тело запроса из `PUT` HTTP-запроса.
Теперь измените файл `main.py`, чтобы принимать тело запроса из `PUT` запроса.
Объявите тело запроса, используя стандартные типы Python, спасибо Pydantic.
Объявите тело, используя стандартные типы Python, спасибо Pydantic.
```Python hl_lines="4 9-12 25-27"
from typing import Union
@@ -324,7 +318,7 @@ def update_item(item_id: int, item: Item):
Перейдите на <a href="http://127.0.0.1:8000/docs" class="external-link" target="_blank">http://127.0.0.1:8000/docs</a>.
* Интерактивная документация API будет автоматически обновлена, включая новое тело запроса:
* Интерактивная документация API будет автоматически обновлена, включая новое тело:
![Swagger UI](https://fastapi.tiangolo.com/img/index/index-03-swagger-02.png)
@@ -340,13 +334,13 @@ def update_item(item_id: int, item: Item):
Теперь откройте <a href="http://127.0.0.1:8000/redoc" class="external-link" target="_blank">http://127.0.0.1:8000/redoc</a>.
* Альтернативная документация также отразит новый параметр запроса и тело запроса:
* Альтернативная документация также отразит новый параметр запроса и тело:
![ReDoc](https://fastapi.tiangolo.com/img/index/index-06-redoc-02.png)
### Подведём итоги { #recap }
Итак, вы объявляете **один раз** типы параметров, тело запроса и т.д. как параметры функции.
Итак, вы объявляете **один раз** типы параметров, тела запроса и т.д. как параметры функции.
Вы делаете это с помощью стандартных современных типов Python.
@@ -396,13 +390,13 @@ item: Item
Возвращаясь к предыдущему примеру кода, **FastAPI** будет:
* Валидировать наличие `item_id` в пути для `GET` и `PUT` HTTP-запросов.
* Валидировать, что `item_id` имеет тип `int` для `GET` и `PUT` HTTP-запросов.
* Валидировать наличие `item_id` в пути для `GET` и `PUT` запросов.
* Валидировать, что `item_id` имеет тип `int` для `GET` и `PUT` запросов.
* Если это не так, клиент увидит полезную понятную ошибку.
* Проверять, есть ли необязательный параметр запроса с именем `q` (например, `http://127.0.0.1:8000/items/foo?q=somequery`) для `GET` HTTP-запросов.
* Проверять, есть ли необязательный параметр запроса с именем `q` (например, `http://127.0.0.1:8000/items/foo?q=somequery`) для `GET` запросов.
* Поскольку параметр `q` объявлен с `= None`, он необязателен.
* Без `None` он был бы обязательным (как тело запроса в случае с `PUT`).
* Для `PUT` HTTP-запросов к `/items/{item_id}` читать тело запроса как JSON:
* Для `PUT` запросов к `/items/{item_id}` читать тело запроса как JSON:
* Проверять, что есть обязательный атрибут `name`, который должен быть `str`.
* Проверять, что есть обязательный атрибут `price`, который должен быть `float`.
* Проверять, что есть необязательный атрибут `is_offer`, который должен быть `bool`, если он присутствует.
@@ -441,11 +435,11 @@ item: Item
Более полный пример с дополнительными возможностями см. в <a href="https://fastapi.tiangolo.com/ru/tutorial/">Учебник - Руководство пользователя</a>.
**Осторожно, спойлер**: учебник - руководство пользователя включает:
**Осторожно, спойлер**: учебник - руководство включает:
* Объявление **параметров** из других источников: **HTTP-заголовки**, **cookies**, **поля формы** и **файлы**.
* Как задать **ограничения валидации** вроде `maximum_length` или `regex`.
* Очень мощную и простую в использовании систему **<abbr title="также известна как: компоненты, ресурсы, провайдеры, сервисы, инъекции">внедрения зависимостей</abbr>**.
* Очень мощную и простую в использовании систему **<abbr title="также известная как: компоненты, ресурсы, провайдеры, сервисы, инъекции">внедрения зависимостей</abbr>**.
* Безопасность и аутентификацию, включая поддержку **OAuth2** с **JWT токенами** и **HTTP Basic** аутентификацию.
* Более продвинутые (но столь же простые) приёмы объявления **глубоко вложенных JSON-моделей** (спасибо Pydantic).
* Интеграцию **GraphQL** с <a href="https://strawberry.rocks" class="external-link" target="_blank">Strawberry</a> и другими библиотеками.
@@ -530,11 +524,11 @@ FastAPI зависит от Pydantic и Starlette.
* <a href="https://www.python-httpx.org" target="_blank"><code>httpx</code></a> — обязателен, если вы хотите использовать `TestClient`.
* <a href="https://jinja.palletsprojects.com" target="_blank"><code>jinja2</code></a> — обязателен, если вы хотите использовать конфигурацию шаблонов по умолчанию.
* <a href="https://github.com/Kludex/python-multipart" target="_blank"><code>python-multipart</code></a> - обязателен, если вы хотите поддерживать <abbr title="преобразование строки, полученной из HTTP-запроса, в данные Python">«парсинг»</abbr> форм через `request.form()`.
* <a href="https://github.com/Kludex/python-multipart" target="_blank"><code>python-multipart</code></a> обязателен, если вы хотите поддерживать <abbr title="преобразование строки, полученной из HTTP-запроса, в данные Python">«парсинг»</abbr> форм через `request.form()`.
Используется FastAPI:
* <a href="https://www.uvicorn.dev" target="_blank"><code>uvicorn</code></a> — сервер, который загружает и «отдаёт» ваше приложение. Включает `uvicorn[standard]`, содержащий некоторые зависимости (например, `uvloop`), нужные для высокой производительности.
* <a href="https://www.uvicorn.dev" target="_blank"><code>uvicorn</code></a> — сервер, который загружает и обслуживает ваше приложение. Включает `uvicorn[standard]`, содержащий некоторые зависимости (например, `uvloop`), нужные для высокой производительности.
* `fastapi-cli[standard]` — чтобы предоставить команду `fastapi`.
* Включает `fastapi-cloud-cli`, который позволяет развернуть ваше приложение FastAPI в <a href="https://fastapicloud.com" class="external-link" target="_blank">FastAPI Cloud</a>.

View File

@@ -1,4 +1,4 @@
# Большие приложения — несколько файлов { #bigger-applications-multiple-files }
# Большие приложения, в которых много файлов { #bigger-applications-multiple-files }
При построении приложения или веб-API нам редко удается поместить всё в один файл.
@@ -31,7 +31,7 @@
/// tip | Подсказка
Есть несколько файлов `__init__.py`: по одному в каждом каталоге или подкаталоге.
Обратите внимание, что в каждом каталоге и подкаталоге имеется файл `__init__.py`
Это как раз то, что позволяет импортировать код из одного файла в другой.
@@ -43,63 +43,61 @@ from app.routers import items
///
* Всё помещается в каталоге `app`. В нём также находится пустой файл `app/__init__.py`. Таким образом, `app` является "Python-пакетом" (коллекцией "Python-модулей"): `app`.
* Он содержит файл `app/main.py`. Данный файл является частью Python-пакета (т.е. находится внутри каталога, содержащего файл `__init__.py`), и, соответственно, он является модулем этого пакета: `app.main`.
* Всё помещается в каталоге `app`. В нём также находится пустой файл `app/__init__.py`. Таким образом, `app` является "Python-пакетом" (коллекцией модулей Python).
* Он содержит файл `app/main.py`. Данный файл является частью пакета (т.е. находится внутри каталога, содержащего файл `__init__.py`), и, соответственно, он является модулем пакета: `app.main`.
* Он также содержит файл `app/dependencies.py`, который также, как и `app/main.py`, является модулем: `app.dependencies`.
* Здесь также находится подкаталог `app/routers/`, содержащий `__init__.py`. Он является Python-подпакетом: `app.routers`.
* Файл `app/routers/items.py` находится внутри пакета `app/routers/`. Таким образом, он является подмодулем: `app.routers.items`.
* Точно так же `app/routers/users.py` является ещё одним подмодулем: `app.routers.users`.
* Подкаталог `app/internal/`, содержащий файл `__init__.py`, является ещё одним Python-подпакетом: `app.internal`.
* А файл `app/internal/admin.py` является ещё одним подмодулем: `app.internal.admin`.
* Здесь также находится подкаталог `app/routers/`, содержащий `__init__.py`. Он является суб-пакетом: `app.routers`.
* Файл `app/routers/items.py` находится внутри пакета `app/routers/`. Таким образом, он является суб-модулем: `app.routers.items`.
* Точно также `app/routers/users.py` является ещё одним суб-модулем: `app.routers.users`.
* Подкаталог `app/internal/`, содержащий файл `__init__.py`, является ещё одним суб-пакетом: `app.internal`.
* А файл `app/internal/admin.py` является ещё одним суб-модулем: `app.internal.admin`.
<img src="/img/tutorial/bigger-applications/package.drawio.svg">
Та же самая файловая структура приложения, но с комментариями:
```bash
```
.
├── app # "app" пакет
│   ├── __init__.py # этот файл превращает "app" в "Python-пакет"
│   ├── main.py # модуль "main", напр.: import app.main
│   ├── dependencies.py # модуль "dependencies", напр.: import app.dependencies
│   └── routers # подпакет "routers"
│   │ ├── __init__.py # превращает "routers" в подпакет
│   │ ├── items.py # подмодуль "items", напр.: import app.routers.items
│   │ └── users.py # подмодуль "users", напр.: import app.routers.users
│   └── internal # подпакет "internal"
│   ├── __init__.py # превращает "internal" в подпакет
│   └── admin.py # подмодуль "admin", напр.: import app.internal.admin
│   └── routers # суб-пакет "routers"
│   │ ├── __init__.py # превращает "routers" в суб-пакет
│   │ ├── items.py # суб-модуль "items", напр.: import app.routers.items
│   │ └── users.py # суб-модуль "users", напр.: import app.routers.users
│   └── internal # суб-пакет "internal"
│   ├── __init__.py # превращает "internal" в суб-пакет
│   └── admin.py # суб-модуль "admin", напр.: import app.internal.admin
```
## `APIRouter` { #apirouter }
Давайте предположим, что для работы с пользователями используется отдельный файл (подмодуль) `/app/routers/users.py`.
Давайте предположим, что для работы с пользователями используется отдельный файл (суб-модуль) `/app/routers/users.py`.
Вы хотите отделить *операции пути*, связанные с пользователями, от остального кода, чтобы сохранить порядок.
Для лучшей организации приложения, вы хотите отделить операции пути, связанные с пользователями, от остального кода.
Но это всё равно часть того же приложения/веб-API на **FastAPI** (часть того же «Python-пакета»).
Но так, чтобы эти операции по-прежнему оставались частью **FastAPI** приложения/веб-API (частью одного пакета)
С помощью `APIRouter` вы можете создать *операции пути* для этого модуля.
С помощью `APIRouter` вы можете создать *операции пути* (*эндпоинты*) для данного модуля.
### Импорт `APIRouter` { #import-apirouter }
Точно так же, как и в случае с классом `FastAPI`, вам нужно импортировать и создать его «экземпляр»:
Точно также, как и в случае с классом `FastAPI`, вам нужно импортировать и создать объект класса `APIRouter`.
{* ../../docs_src/bigger_applications/app_an_py39/routers/users.py hl[1,3] title["app/routers/users.py"] *}
### *Операции пути* с `APIRouter` { #path-operations-with-apirouter }
### Создание *эндпоинтов* с помощью `APIRouter` { #path-operations-with-apirouter }
И затем вы используете его, чтобы объявить ваши *операции пути*.
Используйте его так же, как вы использовали бы класс `FastAPI`:
В дальнейшем используйте `APIRouter` для объявления *эндпоинтов*, точно также, как вы используете класс `FastAPI`:
{* ../../docs_src/bigger_applications/app_an_py39/routers/users.py hl[6,11,16] title["app/routers/users.py"] *}
Вы можете думать об `APIRouter` как об «мини-классе `FastAPI`».
Вы можете думать об `APIRouter` как об "уменьшенной версии" класса FastAPI`.
Поддерживаются все те же опции.
`APIRouter` поддерживает все те же самые опции.
Все те же `parameters`, `responses`, `dependencies`, `tags` и т.д.
`APIRouter` поддерживает все те же самые параметры, такие как `parameters`, `responses`, `dependencies`, `tags`, и т. д.
/// tip | Подсказка
@@ -107,21 +105,21 @@ from app.routers import items
///
Мы собираемся подключить данный `APIRouter` к нашему основному приложению на `FastAPI`, но сначала давайте проверим зависимости и ещё один `APIRouter`.
Мы собираемся подключить данный `APIRouter` к нашему основному приложению на `FastAPI`, но сначала давайте проверим зависимости и создадим ещё один модуль с `APIRouter`.
## Зависимости { #dependencies }
Мы видим, что нам понадобятся некоторые зависимости, которые будут использоваться в нескольких местах приложения.
Нам понадобятся некоторые зависимости, которые мы будем использовать в разных местах нашего приложения.
Поэтому мы поместим их в отдельный модуль `dependencies` (`app/dependencies.py`).
Мы поместим их в отдельный модуль `dependencies` (`app/dependencies.py`).
Теперь мы воспользуемся простой зависимостью, чтобы прочитать кастомный HTTP-заголовок `X-Token`:
Теперь мы воспользуемся простой зависимостью, чтобы прочитать кастомизированный `X-Token` из заголовка:
{* ../../docs_src/bigger_applications/app_an_py39/dependencies.py hl[3,6:8] title["app/dependencies.py"] *}
/// tip | Подсказка
Для простоты мы воспользовались выдуманным заголовком.
Для простоты мы воспользовались неким воображаемым заголовоком.
В реальных случаях для получения наилучших результатов используйте интегрированные [утилиты безопасности](security/index.md){.internal-link target=_blank}.
@@ -129,29 +127,30 @@ from app.routers import items
## Ещё один модуль с `APIRouter` { #another-module-with-apirouter }
Давайте также предположим, что у вас есть эндпоинты, отвечающие за обработку «items» в вашем приложении, и они находятся в модуле `app/routers/items.py`.
Давайте также предположим, что у вас есть *эндпоинты*, отвечающие за обработку "items", и они находятся в модуле `app/routers/items.py`.
У вас определены *операции пути* для:
У вас определены следующие *операции пути* (*эндпоинты*):
* `/items/`
* `/items/{item_id}`
Тут всё та же структура, как и в случае с `app/routers/users.py`.
Тут всё точно также, как и в ситуации с `app/routers/users.py`.
Но мы хотим поступить умнее и слегка упростить код.
Но теперь мы хотим поступить немного умнее и слегка упростить код.
Мы знаем, что все *операции пути* этого модуля имеют одинаковые:
Мы знаем, что все *эндпоинты* данного модуля имеют некоторые общие свойства:
* `prefix` пути: `/items`.
* `tags`: (один единственный тег: `items`).
* Дополнительные `responses`.
* `dependencies`: всем им нужна та зависимость `X-Token`, которую мы создали.
* Префикс пути: `/items`.
* Теги: (один единственный тег: `items`).
* Дополнительные ответы (responses)
* Зависимости: использование созданной нами зависимости `X-token`
Таким образом, вместо того чтобы добавлять всё это в каждую *операцию пути*, мы можем добавить это в `APIRouter`.
Таким образом, вместо того чтобы добавлять все эти свойства в функцию каждого отдельного *эндпоинта*,
мы добавим их в `APIRouter`.
{* ../../docs_src/bigger_applications/app_an_py39/routers/items.py hl[5:10,16,21] title["app/routers/items.py"] *}
Так как путь каждой *операции пути* должен начинаться с `/`, как здесь:
Так как каждый *эндпоинт* начинается с символа `/`:
```Python hl_lines="1"
@router.get("/{item_id}")
@@ -163,74 +162,73 @@ async def read_item(item_id: str):
В нашем случае префиксом является `/items`.
Мы также можем добавить список `tags` и дополнительные `responses`, которые будут применяться ко всем *операциям пути*, включённым в этот маршрутизатор.
Мы также можем добавить в наш маршрутизатор (router) список `тегов` (`tags`) и дополнительных `ответов` (`responses`), которые являются общими для каждого *эндпоинта*.
И ещё мы можем добавить список `dependencies`, которые будут добавлены ко всем *операциям пути* в маршрутизаторе и будут выполняться/разрешаться для каждого HTTP-запроса к ним.
И ещё мы можем добавить в наш маршрутизатор список `зависимостей`, которые должны вызываться при каждом обращении к *эндпоинтам*.
/// tip | Подсказка
Обратите внимание, что так же, как и в случае с [зависимостями в декораторах *операций пути*](dependencies/dependencies-in-path-operation-decorators.md){.internal-link target=_blank}, никакое значение не будет передано в вашу *функцию-обработчик пути*.
Обратите внимание, что также, как и в случае с зависимостями в декораторах *эндпоинтов* ([зависимости в декораторах операций пути](dependencies/dependencies-in-path-operation-decorators.md){.internal-link target=_blank}), никакого значения в *функцию эндпоинта* передано не будет.
///
В результате пути для items теперь такие:
В результате мы получим следующие эндпоинты:
* `/items/`
* `/items/{item_id}`
...как мы и планировали.
* Они будут помечены списком тегов, содержащим одну строку `"items"`.
* Эти «теги» особенно полезны для систем автоматической интерактивной документации (с использованием OpenAPI).
* Все они будут включать предопределённые `responses`.
* Все эти *операции пути* будут иметь список `dependencies`, вычисляемых/выполняемых перед ними.
* Если вы также объявите зависимости в конкретной *операции пути*, **они тоже будут выполнены**.
* Сначала выполняются зависимости маршрутизатора, затем [`dependencies` в декораторе](dependencies/dependencies-in-path-operation-decorators.md){.internal-link target=_blank}, и затем обычные параметрические зависимости.
* Вы также можете добавить [`Security`-зависимости с `scopes`](../advanced/security/oauth2-scopes.md){.internal-link target=_blank}.
* Они будут помечены тегами из заданного списка, в нашем случае это `"items"`.
* Эти теги особенно полезны для системы автоматической интерактивной документации (с использованием OpenAPI).
* Каждый из них будет включать предопределенные ответы `responses`.
* Каждый *эндпоинт* будет иметь список зависимостей (`dependencies`), исполняемых перед вызовом *эндпоинта*.
* Если вы определили зависимости в самой операции пути, **то она также будет выполнена**.
* Сначала выполняются зависимости маршрутизатора, затем вызываются [зависимости в декораторе](dependencies/dependencies-in-path-operation-decorators.md){.internal-link target=_blank}, и, наконец, обычные параметрические зависимости.
* Вы также можете добавить [зависимости `Security` с `scopes`](../advanced/security/oauth2-scopes.md){.internal-link target=_blank}.
/// tip | Подсказка
Например, с помощью зависимостей в `APIRouter` мы можем потребовать аутентификации для доступа ко всей группе *операций пути*. Даже если зависимости не добавляются по отдельности к каждой из них.
Например, с помощью зависимостей в `APIRouter` мы можем потребовать аутентификации для доступа ко всей группе *эндпоинтов*, не указывая зависимости для каждой отдельной функции *эндпоинта*.
///
/// check | Заметка
Параметры `prefix`, `tags`, `responses` и `dependencies` — это (как и во многих других случаях) просто возможность **FastAPI**, помогающая избежать дублирования кода.
Параметры `prefix`, `tags`, `responses` и `dependencies` относятся к функционалу **FastAPI**, помогающему избежать дублирования кода.
///
### Импорт зависимостей { #import-the-dependencies }
Этот код находится в модуле `app.routers.items`, в файле `app/routers/items.py`.
Наш код находится в модуле `app.routers.items` (файл `app/routers/items.py`).
И нам нужно получить функцию зависимости из модуля `app.dependencies`, файла `app/dependencies.py`.
И нам нужно вызвать функцию зависимости из модуля `app.dependencies` (файл `app/dependencies.py`).
Поэтому мы используем относительный импорт с `..` для зависимостей:
Мы используем операцию относительного импорта `..` для импорта зависимости:
{* ../../docs_src/bigger_applications/app_an_py39/routers/items.py hl[3] title["app/routers/items.py"] *}
#### Как работает относительный импорт { #how-relative-imports-work }
#### Как работает относительный импорт? { #how-relative-imports-work }
/// tip | Подсказка
Если вы прекрасно знаете, как работает импорт, переходите к следующему разделу ниже.
Если вы прекрасно знаете, как работает импорт в Python, то переходите к следующему разделу.
///
Одна точка `.`, как здесь:
Одна точка `.`, как в данном примере:
```Python
from .dependencies import get_token_header
```
означает:
* Начать в том же пакете, в котором находится этот модуль (файл `app/routers/items.py`) (каталог `app/routers/`)...
* найти модуль `dependencies` (воображаемый файл `app/routers/dependencies.py`)...
* и импортировать из него функцию `get_token_header`.
* Начните с пакета, в котором находится данный модуль (файл `app/routers/items.py` расположен в каталоге `app/routers/`)...
* ... найдите модуль `dependencies` (файл `app/routers/dependencies.py`)...
* ... и импортируйте из него функцию `get_token_header`.
Но такого файла не существует, наши зависимости находятся в файле `app/dependencies.py`.
К сожалению, такого файла не существует, и наши зависимости находятся в файле `app/dependencies.py`.
Вспомните, как выглядит файловая структура нашего приложения:
@@ -238,7 +236,7 @@ from .dependencies import get_token_header
---
Две точки `..`, как здесь:
Две точки `..`, как в данном примере:
```Python
from ..dependencies import get_token_header
@@ -246,12 +244,12 @@ from ..dependencies import get_token_header
означают:
* Начать в том же пакете, в котором находится этот модуль (файл `app/routers/items.py`) (каталог `app/routers/`)...
* перейти в родительский пакет (каталог `app/`)...
* и там найти модуль `dependencies` (файл `app/dependencies.py`)...
* и импортировать из него функцию `get_token_header`.
* Начните с пакета, в котором находится данный модуль (файл `app/routers/items.py` находится в каталоге `app/routers/`)...
* ... перейдите в родительский пакет (каталог `app/`)...
* ... найдите в нём модуль `dependencies` (файл `app/dependencies.py`)...
* ... и импортируйте из него функцию `get_token_header`.
Это работает корректно! 🎉
Это работает верно! 🎉
---
@@ -263,29 +261,29 @@ from ...dependencies import get_token_header
то это бы означало:
* Начать в том же пакете, в котором находится этот модуль (файл `app/routers/items.py`) расположен в (каталоге `app/routers/`)...
* перейти в родительский пакет (каталог `app/`)...
* затем перейти в родительский пакет этого пакета (родительского пакета нет, `app` верхний уровень 😱)...
* и там найти модуль `dependencies` (файл `app/dependencies.py`)...
* и импортировать из него функцию `get_token_header`.
* Начните с пакета, в котором находится данный модуль (файл `app/routers/items.py` находится в каталоге `app/routers/`)...
* ... перейдите в родительский пакет (каталог `app/`)...
* ... затем перейдите в родительский пакет текущего пакета (такого пакета не существует, `app` находится на самом верхнем уровне 😱)...
* ... найдите в нём модуль `dependencies` (файл `app/dependencies.py`)...
* ... и импортируйте из него функцию `get_token_header`.
Это ссылалось бы на какой-то пакет выше `app/`, со своим файлом `__init__.py` и т.п. Но у нас такого нет. Поэтому это вызвало бы ошибку в нашем примере. 🚨
Это будет относиться к некоторому пакету, находящемуся на один уровень выше чем `app/` и содержащему свой собственный файл `__init__.py`. Но ничего такого у нас нет. Поэтому это приведет к ошибке в нашем примере. 🚨
Но теперь вы знаете, как это работает, так что можете использовать относительные импорты в своих приложениях, независимо от того, насколько они сложные. 🤓
Теперь вы знаете, как работает импорт в Python, и сможете использовать относительное импортирование в своих собственных приложениях любого уровня сложности. 🤓
### Добавление пользовательских `tags`, `responses` и `dependencies` { #add-some-custom-tags-responses-and-dependencies }
### Добавление пользовательских тегов (`tags`), ответов (`responses`) и зависимостей (`dependencies`) { #add-some-custom-tags-responses-and-dependencies }
Мы не добавляем префикс `/items` и `tags=["items"]` к каждой *операции пути*, потому что мы добавили их в `APIRouter`.
Мы не будем добавлять префикс `/items` и список тегов `tags=["items"]` для каждого *эндпоинта*, т.к. мы уже их добавили с помощью `APIRouter`.
Но мы всё равно можем добавить _ещё_ `tags`, которые будут применяться к конкретной *операции пути*, а также дополнительные `responses`, специфичные для этой *операции пути*:
Но помимо этого мы можем добавить новые теги для каждого отдельного *эндпоинта*, а также некоторые дополнительные ответы (`responses`), характерные для данного *эндпоинта*:
{* ../../docs_src/bigger_applications/app_an_py39/routers/items.py hl[30:31] title["app/routers/items.py"] *}
/// tip | Подсказка
Эта последняя операция пути будет иметь комбинацию тегов: `["items", "custom"]`.
Последний *эндпоинт* будет иметь следующую комбинацию тегов: `["items", "custom"]`.
И в документации у неё будут оба ответа: один для `404` и один для `403`.
А также в его документации будут содержаться оба ответа: один для `404` и другой для `403`.
///
@@ -295,29 +293,29 @@ from ...dependencies import get_token_header
Именно сюда вы импортируете и именно здесь вы используете класс `FastAPI`.
Это основной файл вашего приложения, который связывает всё воедино.
Это основной файл вашего приложения, который объединяет всё в одно целое.
И так как большая часть вашей логики теперь будет находиться в отдельных специфичных модулях, основной файл будет довольно простым.
И теперь, когда большая часть логики приложения разделена на отдельные модули, основной файл `app/main.py` будет достаточно простым.
### Импорт `FastAPI` { #import-fastapi }
Вы импортируете и создаёте класс `FastAPI` как обычно.
Вы импортируете и создаете класс `FastAPI` как обычно.
И мы даже можем объявить [глобальные зависимости](dependencies/global-dependencies.md){.internal-link target=_blank}, которые будут объединены с зависимостями для каждого `APIRouter`:
Мы даже можем объявить [глобальные зависимости](dependencies/global-dependencies.md){.internal-link target=_blank}, которые будут объединены с зависимостями для каждого отдельного маршрутизатора:
{* ../../docs_src/bigger_applications/app_an_py39/main.py hl[1,3,7] title["app/main.py"] *}
### Импорт `APIRouter` { #import-the-apirouter }
Теперь мы импортируем другие подмодули, содержащие `APIRouter`:
Теперь мы импортируем другие суб-модули, содержащие `APIRouter`:
{* ../../docs_src/bigger_applications/app_an_py39/main.py hl[4:5] title["app/main.py"] *}
Так как файлы `app/routers/users.py` и `app/routers/items.py` являются подмодулями, входящими в один и тот же Python-пакет `app`, мы можем использовать одну точку `.` для импорта через «относительные импорты».
Так как файлы `app/routers/users.py` и `app/routers/items.py` являются суб-модулями одного и того же Python-пакета `app`, то мы сможем их импортировать, воспользовавшись операцией относительного импорта `.`.
### Как работает импорт { #how-the-importing-works }
### Как работает импорт? { #how-the-importing-works }
Этот фрагмент:
Данная строка кода:
```Python
from .routers import items, users
@@ -325,15 +323,15 @@ from .routers import items, users
означает:
* Начать в том же пакете, в котором находится этот модуль (файл `app/main.py`) расположен в (каталоге `app/`)...
* найти подпакет `routers` (каталог `app/routers/`)...
* и импортировать из него подмодули `items` (файл `app/routers/items.py`) и `users` (файл `app/routers/users.py`)...
* Начните с пакета, в котором содержится данный модуль (файл `app/main.py` содержится в каталоге `app/`)...
* ... найдите суб-пакет `routers` (каталог `app/routers/`)...
* ... и из него импортируйте суб-модули `items` (файл `app/routers/items.py`) и `users` (файл `app/routers/users.py`)...
В модуле `items` будет переменная `router` (`items.router`). Это та же самая, которую мы создали в файле `app/routers/items.py`, это объект `APIRouter`.
В модуле `items` содержится переменная `router` (`items.router`), та самая, которую мы создали в файле `app/routers/items.py`, она является объектом класса `APIRouter`.
И затем мы делаем то же самое для модуля `users`.
И затем мы сделаем то же самое для модуля `users`.
Мы также могли бы импортировать их так:
Мы также могли бы импортировать и другим методом:
```Python
from app.routers import items, users
@@ -341,44 +339,44 @@ from app.routers import items, users
/// info | Примечание
Первая версия — это «относительный импорт»:
Первая версия является примером относительного импорта:
```Python
from .routers import items, users
```
Вторая версия — это «абсолютный импорт»:
Вторая версия является примером абсолютного импорта:
```Python
from app.routers import items, users
```
Чтобы узнать больше о Python-пакетах и модулях, прочитайте <a href="https://docs.python.org/3/tutorial/modules.html" class="external-link" target="_blank">официальную документацию Python о модулях</a>.
Узнать больше о пакетах и модулях в Python вы можете из <a href="https://docs.python.org/3/tutorial/modules.html" class="external-link" target="_blank">официальной документации Python о модулях</a>
///
### Избегайте конфликтов имён { #avoid-name-collisions }
### Избегайте конфликтов имен { #avoid-name-collisions }
Мы импортируем подмодуль `items` напрямую, вместо того чтобы импортировать только его переменную `router`.
Вместо того чтобы импортировать только переменную `router`, мы импортируем непосредственно суб-модуль `items`.
Это потому, что у нас также есть другая переменная с именем `router` в подмодуле `users`.
Мы делаем это потому, что у нас есть ещё одна переменная `router` в суб-модуле `users`.
Если бы мы импортировали их одну за другой, как здесь:
Если бы мы импортировали их одну за другой, как показано в примере:
```Python
from .routers.items import router
from .routers.users import router
```
то `router` из `users` перезаписал бы `router` из `items`, и мы не смогли бы использовать их одновременно.
то переменная `router` из `users` переписал бы переменную `router` из `items`, и у нас не было бы возможности использовать их одновременно.
Поэтому, чтобы иметь возможность использовать обе в одном файле, мы импортируем подмодули напрямую:
Поэтому, для того чтобы использовать обе эти переменные в одном файле, мы импортировали соответствующие суб-модули:
{* ../../docs_src/bigger_applications/app_an_py39/main.py hl[5] title["app/main.py"] *}
### Подключение `APIRouter` для `users` и `items` { #include-the-apirouters-for-users-and-items }
### Подключение маршрутизаторов (`APIRouter`) для `users` и для `items` { #include-the-apirouters-for-users-and-items }
Теперь давайте подключим `router` из подмодулей `users` и `items`:
Давайте подключим маршрутизаторы (`router`) из суб-модулей `users` и `items`:
{* ../../docs_src/bigger_applications/app_an_py39/main.py hl[10:11] title["app/main.py"] *}
@@ -390,78 +388,79 @@ from .routers.users import router
///
С помощью `app.include_router()` мы можем добавить каждый `APIRouter` в основное приложение `FastAPI`.
С помощью `app.include_router()` мы можем добавить каждый из маршрутизаторов (`APIRouter`) в основное приложение `FastAPI`.
Он включит все маршруты этого маршрутизатора как часть приложения.
Он подключит все маршруты заданного маршрутизатора к нашему приложению.
/// note | Технические детали
Фактически, внутри он создаст *операцию пути* для каждой *операции пути*, объявленной в `APIRouter`.
Фактически, внутри он создаст все *операции пути* для каждой операции пути объявленной в `APIRouter`.
Так что под капотом всё будет работать так, как будто всё было одним приложением.
И под капотом всё будет работать так, как будто бы мы имеем дело с одним файлом приложения.
///
/// check | Заметка
При подключении маршрутизаторов не нужно беспокоиться о производительности.
При подключении маршрутизаторов не стоит беспокоиться о производительности.
Это займёт микросекунды и произойдёт только при старте.
Операция подключения займёт микросекунды и понадобится только при запуске приложения.
Так что это не повлияет на производительность. ⚡
Таким образом, это не повлияет на производительность. ⚡
///
### Подключение `APIRouter` с пользовательскими `prefix`, `tags`, `responses` и `dependencies` { #include-an-apirouter-with-a-custom-prefix-tags-responses-and-dependencies }
### Подключение `APIRouter` с пользовательскими префиксом (`prefix`), тегами (`tags`), ответами (`responses`), и зависимостями (`dependencies`) { #include-an-apirouter-with-a-custom-prefix-tags-responses-and-dependencies }
Теперь давайте представим, что ваша организация передала вам файл `app/internal/admin.py`.
Он содержит `APIRouter` с некоторыми административными *операциями пути*, которые ваша организация использует в нескольких проектах.
Он содержит `APIRouter` с некоторыми *эндпоитами* администрирования, которые ваша организация использует для нескольких проектов.
Для этого примера всё будет очень просто. Но допустим, что поскольку он используется совместно с другими проектами в организации, мы не можем модифицировать его и добавить `prefix`, `dependencies`, `tags` и т.д. непосредственно в `APIRouter`:
В данном примере это сделать очень просто. Но давайте предположим, что поскольку файл используется для нескольких проектов,
то мы не можем модифицировать его, добавляя префиксы (`prefix`), зависимости (`dependencies`), теги (`tags`), и т.д. непосредственно в `APIRouter`:
{* ../../docs_src/bigger_applications/app_an_py39/internal/admin.py hl[3] title["app/internal/admin.py"] *}
Но мы всё равно хотим задать пользовательский `prefix` при подключении `APIRouter`, чтобы все его *операции пути* начинались с `/admin`, хотим защитить его с помощью `dependencies`, которые у нас уже есть для этого проекта, и хотим включить `tags` и `responses`.
Но, несмотря на это, мы хотим использовать кастомный префикс (`prefix`) для подключенного маршрутизатора (`APIRouter`), в результате чего, каждая *операция пути* будет начинаться с `/admin`. Также мы хотим защитить наш маршрутизатор с помощью зависимостей, созданных для нашего проекта. И ещё мы хотим включить теги (`tags`) и ответы (`responses`).
Мы можем объявить всё это, не изменяя исходный `APIRouter`, передав эти параметры в `app.include_router()`:
Мы можем применить все вышеперечисленные настройки, не изменяя начальный `APIRouter`. Нам всего лишь нужно передать нужные параметры в `app.include_router()`.
{* ../../docs_src/bigger_applications/app_an_py39/main.py hl[14:17] title["app/main.py"] *}
Таким образом исходный `APIRouter` не будет модифицирован, и мы сможем использовать файл `app/internal/admin.py` сразу в нескольких проектах организации.
Таким образом, оригинальный `APIRouter` не будет модифицирован, и мы сможем использовать файл `app/internal/admin.py` сразу в нескольких проектах организации.
В результате в нашем приложении каждая из *операций пути* из модуля `admin` будет иметь:
В результате, в нашем приложении каждый *эндпоинт* модуля `admin` будет иметь:
* Префикс `/admin`.
* Тег `admin`.
* Зависимость `get_token_header`.
* Ответ `418`. 🍵
Но это повлияет только на этот `APIRouter` в нашем приложении, а не на любой другой код, который его использует.
Это будет иметь место исключительно для `APIRouter` в нашем приложении, и не затронет любой другой код, использующий его.
Так что, например, другие проекты могут использовать тот же `APIRouter` с другим методом аутентификации.
Например, другие проекты, могут использовать тот же самый `APIRouter` с другими методами аутентификации.
### Подключение *операции пути* { #include-a-path-operation }
### Подключение отдельного *эндпоинта* { #include-a-path-operation }
Мы также можем добавлять *операции пути* напрямую в приложение `FastAPI`.
Мы также можем добавить *эндпоинт* непосредственно в основное приложение `FastAPI`.
Здесь мы делаем это... просто чтобы показать, что можем 🤷:
Здесь мы это делаем ... просто, чтобы показать, что это возможно 🤷:
{* ../../docs_src/bigger_applications/app_an_py39/main.py hl[21:23] title["app/main.py"] *}
и это будет работать корректно вместе со всеми другими *операциями пути*, добавленными через `app.include_router()`.
и это будет работать корректно вместе с другими *эндпоинтами*, добавленными с помощью `app.include_router()`.
/// info | Очень технические детали
/// info | Сложные технические детали
**Примечание**: это очень техническая деталь, которую, вероятно, можно **просто пропустить**.
**Примечание**: это сложная техническая деталь, которую, скорее всего, **вы можете пропустить**.
---
`APIRouter` не «монтируются», они не изолированы от остального приложения.
Маршрутизаторы (`APIRouter`) не "монтируются" по-отдельности и не изолируются от остального приложения.
Это потому, что мы хотим включить их *операции пути* в OpenAPI-схему и пользовательские интерфейсы.
Это происходит потому, что нужно включить их *эндпоинты* в OpenAPI схему и в интерфейс пользователя.
Так как мы не можем просто изолировать их и «смонтировать» независимо от остального, *операции пути* «клонируются» (пересоздаются), а не включаются напрямую.
В силу того, что мы не можем их изолировать и "примонтировать" независимо от остальных, *эндпоинты* клонируются (пересоздаются) и не подключаются напрямую.
///
@@ -481,24 +480,24 @@ $ fastapi dev app/main.py
Откройте документацию по адресу <a href="http://127.0.0.1:8000/docs" class="external-link" target="_blank">http://127.0.0.1:8000/docs</a>.
Вы увидите автоматическую документацию API, включая пути из всех подмодулей, с использованием корректных путей (и префиксов) и корректных тегов:
Вы увидите автоматическую API документацию. Она включает в себя маршруты из суб-модулей, используя верные маршруты, префиксы и теги:
<img src="/img/tutorial/bigger-applications/image01.png">
## Подключение одного и того же маршрутизатора несколько раз с разными `prefix` { #include-the-same-router-multiple-times-with-different-prefix }
## Подключение существующего маршрута через новый префикс (`prefix`) { #include-the-same-router-multiple-times-with-different-prefix }
Вы можете использовать `.include_router()` несколько раз с *одним и тем же* маршрутизатором, используя разные префиксы.
Вы можете использовать `.include_router()` несколько раз с одним и тем же маршрутом, применив различные префиксы.
Это может быть полезно, например, чтобы предоставить доступ к одному и тому же API с разными префиксами, например `/api/v1` и `/api/latest`.
Это может быть полезным, если нужно предоставить доступ к одному и тому же API через различные префиксы, например, `/api/v1` и `/api/latest`.
Это продвинутое использование, которое вам может и не понадобиться, но оно есть на случай, если понадобится.
Это продвинутый способ, который вам может и не пригодится. Мы приводим его на случай, если вдруг вам это понадобится.
## Подключение `APIRouter` в другой `APIRouter` { #include-an-apirouter-in-another }
## Включение одного маршрутизатора (`APIRouter`) в другой { #include-an-apirouter-in-another }
Точно так же, как вы можете подключить `APIRouter` к приложению `FastAPI`, вы можете подключить `APIRouter` к другому `APIRouter`, используя:
Точно так же, как вы включаете `APIRouter` в приложение `FastAPI`, вы можете включить `APIRouter` в другой `APIRouter`:
```Python
router.include_router(other_router)
```
Убедитесь, что вы сделали это до подключения `router` к приложению `FastAPI`, чтобы *операции пути* из `other_router` также были подключены.
Удостоверьтесь, что вы сделали это до того, как подключить маршрутизатор (`router`) к вашему `FastAPI` приложению, и *эндпоинты* маршрутизатора `other_router` были также подключены.

View File

@@ -2,13 +2,13 @@
## Обновление с заменой при помощи `PUT` { #update-replacing-with-put }
Чтобы обновить элемент, вы можете использовать операцию <a href="https://developer.mozilla.org/en-US/docs/Web/HTTP/Methods/PUT" class="external-link" target="_blank">HTTP `PUT`</a>.
Для полного обновления элемента можно воспользоваться операцией <a href="https://developer.mozilla.org/en-US/docs/Web/HTTP/Methods/PUT" class="external-link" target="_blank">HTTP `PUT`</a>.
Вы можете использовать `jsonable_encoder`, чтобы преобразовать входные данные в данные, которые можно сохранить как JSON (например, в NoSQL-базе данных). Например, преобразование `datetime` в `str`.
{* ../../docs_src/body_updates/tutorial001_py310.py hl[28:33] *}
`PUT` используется для получения данных, которые должны заменить существующие данные.
`PUT` используется для получения данных, которые должны полностью заменить существующие данные.
### Предупреждение о замене { #warning-about-replacing }
@@ -24,11 +24,11 @@
поскольку оно не включает уже сохраненный атрибут `"tax": 20.2`, входная модель примет значение по умолчанию `"tax": 10.5`.
И данные будут сохранены с этим «новым» `tax`, равным `10.5`.
И данные будут сохранены с этим "новым" `tax`, равным `10,5`.
## Частичное обновление с помощью `PATCH` { #partial-updates-with-patch }
Также можно использовать операцию <a href="https://developer.mozilla.org/en-US/docs/Web/HTTP/Methods/PATCH" class="external-link" target="_blank">HTTP `PATCH`</a> для *частичного* обновления данных.
Также можно использовать <a href="https://developer.mozilla.org/en-US/docs/Web/HTTP/Methods/PATCH" class="external-link" target="_blank">HTTP `PATCH`</a> операцию для *частичного* обновления данных.
Это означает, что можно передавать только те данные, которые необходимо обновить, оставляя остальные нетронутыми.
@@ -46,13 +46,19 @@
### Использование параметра `exclude_unset` в Pydantic { #using-pydantics-exclude-unset-parameter }
Если вы хотите получать частичные обновления, очень полезно использовать параметр `exclude_unset` в `.model_dump()` модели Pydantic.
Если необходимо выполнить частичное обновление, то очень полезно использовать параметр `exclude_unset` в методе `.model_dump()` модели Pydantic.
Например, `item.model_dump(exclude_unset=True)`.
В результате будет сгенерирован `dict`, содержащий только те данные, которые были заданы при создании модели `item`, без учета значений по умолчанию.
/// info | Информация
Затем вы можете использовать это для создания `dict` только с теми данными, которые были установлены (отправлены в запросе), опуская значения по умолчанию:
В Pydantic v1 метод назывался `.dict()`, в Pydantic v2 он помечен как устаревший (но все еще поддерживается) и переименован в `.model_dump()`.
Примеры здесь используют `.dict()` для совместимости с Pydantic v1, но если вы можете использовать Pydantic v2, лучше используйте `.model_dump()`.
///
В результате будет сгенерирован словарь, содержащий только те данные, которые были заданы при создании модели `item`, без учета значений по умолчанию. Затем вы можете использовать это для создания словаря только с теми данными, которые были установлены (отправлены в запросе), опуская значения по умолчанию:
{* ../../docs_src/body_updates/tutorial002_py310.py hl[32] *}
@@ -60,6 +66,14 @@
Теперь можно создать копию существующей модели, используя `.model_copy()`, и передать параметр `update` с `dict`, содержащим данные для обновления.
/// info | Информация
В Pydantic v1 метод назывался `.copy()`, в Pydantic v2 он помечен как устаревший (но все еще поддерживается) и переименован в `.model_copy()`.
Примеры здесь используют `.copy()` для совместимости с Pydantic v1, но если вы можете использовать Pydantic v2, лучше используйте `.model_copy()`.
///
Например, `stored_item_model.model_copy(update=update_data)`:
{* ../../docs_src/body_updates/tutorial002_py310.py hl[33] *}
@@ -70,9 +84,9 @@
* (Опционально) использовать `PATCH` вместо `PUT`.
* Извлечь сохранённые данные.
* Поместить эти данные в Pydantic-модель.
* Поместить эти данные в Pydantic модель.
* Сгенерировать `dict` без значений по умолчанию из входной модели (с использованием `exclude_unset`).
* Таким образом, можно обновлять только те значения, которые действительно установлены пользователем, вместо того чтобы переопределять уже сохраненные значения значениями по умолчанию из вашей модели.
* Таким образом, можно обновлять только те значения, которые действительно установлены пользователем, вместо того чтобы переопределять значения, уже сохраненные в модели по умолчанию.
* Создать копию хранимой модели, обновив ее атрибуты полученными частичными обновлениями (с помощью параметра `update`).
* Преобразовать скопированную модель в то, что может быть сохранено в вашей БД (например, с помощью `jsonable_encoder`).
* Это сравнимо с повторным использованием метода модели `.model_dump()`, но при этом происходит проверка (и преобразование) значений в типы данных, которые могут быть преобразованы в JSON, например, `datetime` в `str`.
@@ -83,7 +97,7 @@
/// tip | Подсказка
На самом деле эту же технику можно использовать и для операции HTTP `PUT`.
Эту же технику можно использовать и для операции HTTP `PUT`.
Но в приведенном примере используется `PATCH`, поскольку он был создан именно для таких случаев использования.

View File

@@ -32,10 +32,9 @@
{* ../../docs_src/body/tutorial001_py310.py hl[5:9] *}
Так же, как при объявлении параметров запроса: когда атрибут модели имеет значение по умолчанию, он не обязателен. Иначе он обязателен. Используйте `None`, чтобы сделать его просто необязательным.
Например, модель выше описывает такой JSON "`object`" (или Python `dict`):
Например, модель выше описывает такой JSON "объект" (или Python `dict`):
```JSON
{
@@ -46,7 +45,7 @@
}
```
...так как `description` и `tax` являются необязательными (со значением по умолчанию `None`), такой JSON "`object`" тоже будет корректным:
...так как `description` и `tax` являются необязательными (со значением по умолчанию `None`), такой JSON "объект" тоже будет корректным:
```JSON
{
@@ -74,7 +73,7 @@
* Передаст полученные данные в параметр `item`.
* Поскольку внутри функции вы объявили его с типом `Item`, у вас будет поддержка со стороны редактора кода (автозавершение и т. п.) для всех атрибутов и их типов.
* Сгенерирует определения <a href="https://json-schema.org" class="external-link" target="_blank">JSON Schema</a> для вашей модели; вы можете использовать их и в других местах, если это имеет смысл для вашего проекта.
* Эти схемы будут частью сгенерированной схемы OpenAPI и будут использоваться автоматической документацией <abbr title="User Interfaces - Пользовательские интерфейсы">UIs</abbr>.
* Эти схемы будут частью сгенерированной схемы OpenAPI и будут использоваться автоматической документацией <abbr title="User Interfaces Пользовательские интерфейсы">UIs</abbr>.
## Автоматическая документация { #automatic-docs }
@@ -128,6 +127,14 @@ JSON Schema ваших моделей будет частью сгенериро
{* ../../docs_src/body/tutorial002_py310.py *}
/// info | Информация
В Pydantic v1 метод назывался `.dict()`, в Pydantic v2 он был помечен как устаревший (но всё ещё поддерживается) и переименован в `.model_dump()`.
Примеры здесь используют `.dict()` для совместимости с Pydantic v1, но если вы можете использовать Pydantic v2, используйте `.model_dump()`.
///
## Тело запроса + параметры пути { #request-body-path-parameters }
Вы можете одновременно объявить параметры пути и тело запроса.
@@ -136,7 +143,6 @@ JSON Schema ваших моделей будет частью сгенериро
{* ../../docs_src/body/tutorial003_py310.py hl[15:16] *}
## Тело запроса + параметры пути + параметры запроса { #request-body-path-query-parameters }
Вы также можете одновременно объявить параметры **тела**, **пути** и **запроса**.
@@ -147,7 +153,7 @@ JSON Schema ваших моделей будет частью сгенериро
Параметры функции будут распознаны следующим образом:
* Если параметр также объявлен в **пути**, он будет использоваться как path-параметр.
* Если параметр также объявлен в **пути**, он будет использоваться как параметр пути.
* Если параметр имеет **скалярный тип** (например, `int`, `float`, `str`, `bool` и т. п.), он будет интерпретирован как параметр **запроса**.
* Если параметр объявлен как тип **модели Pydantic**, он будет интерпретирован как **тело** запроса.
@@ -155,7 +161,7 @@ JSON Schema ваших моделей будет частью сгенериро
FastAPI понимает, что значение `q` не является обязательным из-за значения по умолчанию `= None`.
Аннотации типов `str | None` (Python 3.10+) или `Union` в `Union[str, None]` (Python 3.9+) не используются FastAPI для определения обязательности; он узнает, что параметр не обязателен, потому что у него есть значение по умолчанию `= None`.
Аннотации типов `str | None` (Python 3.10+) или `Union[str, None]` (Python 3.9+) не используются FastAPI для определения обязательности; он узнает, что параметр не обязателен, потому что у него есть значение по умолчанию `= None`.
Но добавление аннотаций типов позволит вашему редактору кода лучше вас поддерживать и обнаруживать ошибки.
@@ -163,4 +169,4 @@ FastAPI понимает, что значение `q` не является об
## Без Pydantic { #without-pydantic }
Если вы не хотите использовать модели Pydantic, вы также можете использовать параметры **Body**. См. раздел документации [Тело запроса - Несколько параметров: Единичные значения в теле](body-multiple-params.md#singular-values-in-body){.internal-link target=_blank}.
Если вы не хотите использовать модели Pydantic, вы также можете использовать параметры **Body**. См. раздел документации [Тело Несколько параметров: Единичные значения в теле](body-multiple-params.md#singular-values-in-body){.internal-link target=_blank}.

View File

@@ -22,13 +22,21 @@
{* ../../docs_src/extra_models/tutorial001_py310.py hl[7,9,14,20,22,27:28,31:33,38:39] *}
### Про `**user_in.model_dump()` { #about-user-in-model-dump }
/// info | Информация
#### `.model_dump()` из Pydantic { #pydantics-model-dump }
В Pydantic v1 метод назывался `.dict()`, в Pydantic v2 он помечен как устаревший (но всё ещё поддерживается) и переименован в `.model_dump()`.
`user_in` — это Pydantic-модель класса `UserIn`.
В примерах здесь используется `.dict()` для совместимости с Pydantic v1, но если вы используете Pydantic v2, следует использовать `.model_dump()`.
У Pydantic-моделей есть метод `.model_dump()`, который возвращает `dict` с данными модели.
///
### Про `**user_in.dict()` { #about-user-in-dict }
#### `.dict()` из Pydantic { #pydantics-dict }
`user_in` - это Pydantic-модель класса `UserIn`.
У Pydantic-моделей есть метод `.dict()`, который возвращает `dict` с данными модели.
Поэтому, если мы создадим Pydantic-объект `user_in` таким способом:
@@ -39,10 +47,10 @@ user_in = UserIn(username="john", password="secret", email="john.doe@example.com
и затем вызовем:
```Python
user_dict = user_in.model_dump()
user_dict = user_in.dict()
```
то теперь у нас есть `dict` с данными в переменной `user_dict` (это `dict` вместо объекта Pydantic-модели).
то теперь у нас есть `dict` с данными модели в переменной `user_dict` (это `dict` вместо объекта Pydantic-модели).
И если мы вызовем:
@@ -50,7 +58,7 @@ user_dict = user_in.model_dump()
print(user_dict)
```
мы получим Python `dict` с:
мы можем получить `dict` с такими данными:
```Python
{
@@ -63,7 +71,7 @@ print(user_dict)
#### Распаковка `dict` { #unpacking-a-dict }
Если мы возьмём `dict` наподобие `user_dict` и передадим его в функцию (или класс), используя `**user_dict`, Python его "распакует". Он передаст ключи и значения `user_dict` напрямую как аргументы типа ключ-значение.
Если мы возьмём `dict` наподобие `user_dict` и передадим его в функцию (или класс), используя `**user_dict`, Python распакует его. Он передаст ключи и значения `user_dict` напрямую как аргументы типа ключ-значение.
Поэтому, продолжая описанный выше пример с `user_dict`, написание такого кода:
@@ -71,7 +79,7 @@ print(user_dict)
UserInDB(**user_dict)
```
будет эквивалентно:
Будет работать так же, как примерно такой код:
```Python
UserInDB(
@@ -82,7 +90,7 @@ UserInDB(
)
```
Или, более точно, если использовать `user_dict` напрямую, с любым содержимым, которое он может иметь в будущем:
Или, если для большей точности мы напрямую используем `user_dict` с любым потенциальным содержимым, то этот пример будет выглядеть так:
```Python
UserInDB(
@@ -93,22 +101,22 @@ UserInDB(
)
```
#### Pydantic-модель из содержимого другой { #a-pydantic-model-from-the-contents-of-another }
#### Pydantic-модель из содержимого другой модели { #a-pydantic-model-from-the-contents-of-another }
Как в примере выше мы получили `user_dict` из `user_in.model_dump()`, этот код:
Как в примере выше мы получили `user_dict` из `user_in.dict()`, этот код:
```Python
user_dict = user_in.model_dump()
user_dict = user_in.dict()
UserInDB(**user_dict)
```
будет равнозначен такому:
```Python
UserInDB(**user_in.model_dump())
UserInDB(**user_in.dict())
```
...потому что `user_in.model_dump()` это `dict`, и затем мы указываем, чтобы Python его "распаковал", когда передаём его в `UserInDB` с префиксом `**`.
...потому что `user_in.dict()` - это `dict`, и затем мы указываем, чтобы Python его "распаковал", когда передаём его в `UserInDB` и ставим перед ним `**`.
Таким образом мы получаем Pydantic-модель на основе данных из другой Pydantic-модели.
@@ -117,10 +125,10 @@ UserInDB(**user_in.model_dump())
И затем, если мы добавим дополнительный именованный аргумент `hashed_password=hashed_password` как здесь:
```Python
UserInDB(**user_in.model_dump(), hashed_password=hashed_password)
UserInDB(**user_in.dict(), hashed_password=hashed_password)
```
...то в итоге получится что-то подобное:
... то мы получим что-то подобное:
```Python
UserInDB(
@@ -134,13 +142,13 @@ UserInDB(
/// warning | Предупреждение
Вспомогательные дополнительные функции `fake_password_hasher` и `fake_save_user` используются только для демонстрации возможного потока данных и, конечно, не обеспечивают настоящую безопасность.
Вспомогательные функции `fake_password_hasher` и `fake_save_user` используются только для демонстрации возможного потока данных и, конечно, не обеспечивают настоящую безопасность.
///
## Сократите дублирование { #reduce-duplication }
Сокращение дублирования кода это одна из главных идей **FastAPI**.
Сокращение дублирования кода - это одна из главных идей **FastAPI**.
Поскольку дублирование кода повышает риск появления багов, проблем с безопасностью, проблем десинхронизации кода (когда вы обновляете код в одном месте, но не обновляете в другом), и т.д.
@@ -158,7 +166,7 @@ UserInDB(
## `Union` или `anyOf` { #union-or-anyof }
Вы можете объявить HTTP-ответ как `Union` из двух или более типов. Это означает, что HTTP-ответ может быть любым из них.
Вы можете определить ответ как `Union` из двух или более типов. Это означает, что ответ должен соответствовать одному из них.
Он будет определён в OpenAPI как `anyOf`.
@@ -166,7 +174,7 @@ UserInDB(
/// note | Примечание
При объявлении <a href="https://docs.pydantic.dev/latest/concepts/types/#unions" class="external-link" target="_blank">`Union`</a> сначала указывайте наиболее специфичный тип, затем менее специфичный. В примере ниже более специфичный `PlaneItem` стоит перед `CarItem` в `Union[PlaneItem, CarItem]`.
При объявлении <a href="https://docs.pydantic.dev/latest/concepts/types/#unions" class="external-link" target="_blank">`Union`</a>, сначала указывайте наиболее детальные типы, затем менее детальные. В примере ниже более детальный `PlaneItem` стоит перед `CarItem` в `Union[PlaneItem, CarItem]`.
///
@@ -184,19 +192,19 @@ UserInDB(
some_variable: PlaneItem | CarItem
```
Но если мы поместим это в присваивание `response_model=PlaneItem | CarItem`, мы получим ошибку, потому что Python попытается произвести **некорректную операцию** между `PlaneItem` и `CarItem` вместо того, чтобы интерпретировать это как аннотацию типа.
Но если мы помещаем его в `response_model=PlaneItem | CarItem` мы получим ошибку, потому что Python попытается произвести **некорректную операцию** между `PlaneItem` и `CarItem` вместо того, чтобы интерпретировать это как аннотацию типа.
## Список моделей { #list-of-models }
Таким же образом вы можете объявлять HTTP-ответы, возвращающие списки объектов.
Таким же образом вы можете определять ответы как списки объектов.
Для этого используйте стандартный `typing.List` в Python (или просто `list` в Python 3.9 и выше):
Для этого используйте `typing.List` из стандартной библиотеки Python (или просто `list` в Python 3.9 и выше):
{* ../../docs_src/extra_models/tutorial004_py39.py hl[18] *}
## Ответ с произвольным `dict` { #response-with-arbitrary-dict }
Вы также можете объявить HTTP-ответ, используя обычный произвольный `dict`, объявив только тип ключей и значений, без использования Pydantic-модели.
Вы также можете определить ответ, используя произвольный одноуровневый `dict` и определяя только типы ключей и значений без использования Pydantic-моделей.
Это полезно, если вы заранее не знаете корректных названий полей/атрибутов (которые будут нужны при использовании Pydantic-модели).
@@ -206,6 +214,6 @@ some_variable: PlaneItem | CarItem
## Резюме { #recap }
Используйте несколько Pydantic-моделей и свободно применяйте наследование для каждого случая.
Используйте несколько Pydantic-моделей и свободно применяйте наследование для каждой из них.
Вам не обязательно иметь единственную модель данных для каждой сущности, если эта сущность должна иметь возможность быть в разных "состояниях". Как в случае с "сущностью" пользователя, у которого есть состояние, включающее `password`, `password_hash` и отсутствие пароля.
Вам не обязательно иметь единственную модель данных для каждой сущности, если эта сущность должна иметь возможность быть в разных "состояниях". Как в случае с "сущностью" пользователя, у которого есть состояния с полями `password`, `password_hash` и без пароля.

View File

@@ -8,7 +8,7 @@
Query-параметр `q` имеет тип `str | None`, это означает, что он имеет тип `str`, но также может быть `None`. Значение по умолчанию действительно `None`, поэтому FastAPI будет знать, что он не обязателен.
/// note | Примечание
/// note | Технические детали
FastAPI поймёт, что значение `q` не обязательно, из‑за значения по умолчанию `= None`.
@@ -177,7 +177,7 @@ q: str = Query(default="rick")
**Значение по умолчанию** у **параметра функции** — это **настоящее значение по умолчанию**, что более интуитивно для Python. 😌
Вы можете **вызвать** эту же функцию в **других местах** без FastAPI, и она будет **работать как ожидается**. Если есть **обязательный** параметр (без значения по умолчанию), ваш **редактор** сообщит об ошибке, **Python** тоже пожалуется, если вы запустите её без передачи обязательного параметра.
Вы можете **вызвать** эту же функцию в **других местах** без FastAPI, и она будет **работать как ожидается**. Если есть **обязательный** параметр (без значения по умолчанию), ваш **редактор кода** сообщит об ошибке, **Python** тоже пожалуется, если вы запустите её без передачи обязательного параметра.
Если вы не используете `Annotated`, а применяете **(устаревший) стиль со значением по умолчанию**, то при вызове этой функции без FastAPI в **других местах** вам нужно **помнить** о том, что надо передать аргументы, чтобы всё работало корректно, иначе значения будут не такими, как вы ожидаете (например, вместо `str` будет `QueryInfo` или что-то подобное). И ни редактор, ни Python не будут ругаться при самом вызове функции — ошибка проявится лишь при операциях внутри.
@@ -191,7 +191,7 @@ q: str = Query(default="rick")
## Регулярные выражения { #add-regular-expressions }
Вы можете определить <abbr title="Регулярное выражение (regex, regexp) - это последовательность символов, задающая шаблон поиска для строк.">регулярное выражение</abbr> `pattern`, которому должен соответствовать параметр:
Вы можете определить <abbr title="Регулярное выражение (regex, regexp) это последовательность символов, задающая шаблон поиска для строк.">регулярное выражение</abbr> `pattern`, которому должен соответствовать параметр:
{* ../../docs_src/query_params_str_validations/tutorial004_an_py310.py hl[11] *}
@@ -205,6 +205,20 @@ q: str = Query(default="rick")
Теперь вы знаете, что когда они понадобятся, вы сможете использовать их в **FastAPI**.
### `regex` из Pydantic v1 вместо `pattern` { #pydantic-v1-regex-instead-of-pattern }
До Pydantic версии 2 и до FastAPI 0.100.0 этот параметр назывался `regex`, а не `pattern`, но сейчас он устарел.
Вы всё ещё можете встретить такой код:
//// tab | Pydantic v1
{* ../../docs_src/query_params_str_validations/tutorial004_regex_an_py310.py hl[11] *}
////
Имейте в виду, что это устарело, и код следует обновить на использование нового параметра `pattern`. 🤓
## Значения по умолчанию { #default-values }
Конечно, можно использовать и другие значения по умолчанию, не только `None`.
@@ -265,7 +279,7 @@ q: Annotated[str | None, Query(min_length=3)] = None
http://localhost:8000/items/?q=foo&q=bar
```
вы получите множественные значения *query-параметров* `q` (`foo` и `bar`) в виде Python-`list` внутри вашей *функции-обработчика пути*, в *параметре функции* `q`.
вы получите множественные значения query-параметра `q` (`foo` и `bar`) в виде Python-`list` внутри вашей *функции обработки пути*, в *параметре функции* `q`.
Таким образом, ответ на этот URL будет:
@@ -317,7 +331,7 @@ http://localhost:8000/items/
{* ../../docs_src/query_params_str_validations/tutorial013_an_py39.py hl[9] *}
/// note | Примечание
/// note | Технические детали
Имейте в виду, что в этом случае FastAPI не будет проверять содержимое списка.
@@ -331,7 +345,7 @@ http://localhost:8000/items/
Эта информация будет включена в сгенерированную OpenAPI-схему и использована интерфейсами документации и внешними инструментами.
/// note | Примечание
/// note | Технические детали
Помните, что разные инструменты могут иметь разный уровень поддержки OpenAPI.
@@ -401,7 +415,7 @@ http://127.0.0.1:8000/items/?item-query=foobaritems
///
Например, эта кастомная проверка убеждается, что ID элемента начинается с `isbn-` для номера книги <abbr title="ISBN означает International Standard Book Number - Международный стандартный книжный номер">ISBN</abbr> или с `imdb-` для ID URL фильма на <abbr title="IMDB (Internet Movie Database) - веб‑сайт с информацией о фильмах">IMDB</abbr>:
Например, эта кастомная проверка убеждается, что ID элемента начинается с `isbn-` для номера книги <abbr title="ISBN означает International Standard Book Number Международный стандартный книжный номер">ISBN</abbr> или с `imdb-` для ID URL фильма на <abbr title="IMDB (Internet Movie Database) веб‑сайт с информацией о фильмах">IMDB</abbr>:
{* ../../docs_src/query_params_str_validations/tutorial015_an_py310.py hl[5,16:19,24] *}
@@ -441,7 +455,7 @@ http://127.0.0.1:8000/items/?item-query=foobaritems
Затем с `random.choice()` можно получить **случайное значение** из списка — то есть кортеж вида `(id, name)`. Это будет что‑то вроде `("imdb-tt0371724", "The Hitchhiker's Guide to the Galaxy")`.
После этого мы **присваиваем эти два значения** кортежа переменным `id` и `name`.
После этого мы **распаковываем** эти два значения кортежа в переменные `id` и `name`.
Так что, если пользователь не передал ID элемента, он всё равно получит случайную рекомендацию.

View File

@@ -6,11 +6,11 @@
{* ../../docs_src/response_model/tutorial001_01_py310.py hl[16,21] *}
FastAPI будет использовать этот возвращаемый тип, чтобы:
FastAPI будет использовать этот тип ответа для:
* **Валидировать** возвращаемые данные.
* Если данные невалидны (например, отсутствует поле), это означает, что код *вашего* приложения работает некорректно и возвращает не то, что должен. В таком случае будет возвращена ошибка сервера вместо неправильных данных. Так вы и ваши клиенты можете быть уверены, что получите ожидаемые данные и ожидаемую структуру данных.
* Добавить **JSON Schema** для ответа в OpenAPI *операции пути*.
* **Валидации** возвращаемых данных.
* Если данные невалидны (например, отсутствует поле), это означает, что код *вашего* приложения работает некорректно и возвращает не то, что должен. В таком случае будет возвращена ошибка сервера вместо неправильных данных. Так вы и ваши клиенты можете быть уверены, что получите ожидаемые данные и ожидаемую структуру.
* Добавления **JSON Schema** для ответа в OpenAPI *операции пути*.
* Это будет использовано **автоматической документацией**.
* Это также будет использовано инструментами автоматической генерации клиентского кода.
@@ -23,7 +23,7 @@ FastAPI будет использовать этот возвращаемый т
Бывают случаи, когда вам нужно или хочется возвращать данные, которые не в точности соответствуют объявленному типу.
Например, вы можете хотеть **возвращать словарь** или объект из базы данных, но **объявить его как Pydantic-модель**. Тогда Pydantic-модель выполнит документирование данных, валидацию и т.п. для объекта, который вы вернули (например, словаря или объекта из базы данных).
Например, вы можете хотеть **возвращать словарь (dict)** или объект из базы данных, но **объявить его как Pydantic-модель**. Тогда Pydantic-модель выполнит документирование данных, валидацию и т.п. для объекта, который вы вернули (например, словаря или объекта из базы данных).
Если вы добавите аннотацию возвращаемого типа, инструменты и редакторы кода начнут жаловаться (и будут правы), что функция возвращает тип (например, dict), отличный от объявленного (например, Pydantic-модель).
@@ -47,13 +47,13 @@ FastAPI будет использовать этот возвращаемый т
`response_model` принимает тот же тип, что вы бы объявили для поля Pydantic-модели, то есть это может быть одна Pydantic-модель, а может быть, например, `list` Pydantic-моделей, как `List[Item]`.
FastAPI будет использовать этот `response_model` для документирования, валидации данных и т.п., а также для **конвертации и фильтрации выходных данных** к объявленному типу.
FastAPI будет использовать `response_model` для документации, валидации и т. п., а также для **конвертации и фильтрации выходных данных** к объявленному типу.
/// tip | Совет
Если у вас в редакторе кода, mypy и т.п. включены строгие проверки типов, вы можете объявить возвращаемый тип функции как `Any`.
Если у вас в редакторе кода, mypy и т. п. включены строгие проверки типов, вы можете объявить возвращаемый тип функции как `Any`.
Так вы сообщите редактору, что намеренно возвращаете что угодно. Но FastAPI всё равно выполнит документирование, валидацию, фильтрацию данных и т.д. с помощью `response_model`.
Так вы сообщите редактору, что намеренно возвращаете что угодно. Но FastAPI всё равно выполнит документацию данных, валидацию, фильтрацию и т.д. с помощью `response_model`.
///
@@ -61,7 +61,7 @@ FastAPI будет использовать этот `response_model` для д
Если вы объявите и возвращаемый тип, и `response_model`, приоритет будет у `response_model`, именно его использует FastAPI.
Так вы можете добавить корректные аннотации типов к своим функциям, даже если фактически возвращаете тип, отличный от модели ответа, чтобы ими пользовались редактор кода и инструменты вроде mypy. И при этом FastAPI продолжит выполнять валидацию данных, документацию и т.д. с использованием `response_model`.
Так вы можете добавить корректные аннотации типов к своим функциям, даже если фактически возвращаете тип, отличный от модели ответа, чтобы ими пользовались редактор и инструменты вроде mypy. И при этом FastAPI продолжит выполнять валидацию данных, документацию и т.д. с использованием `response_model`.
Вы также можете указать `response_model=None`, чтобы отключить создание модели ответа для данной *операции пути*. Это может понадобиться, если вы добавляете аннотации типов для вещей, не являющихся валидными полями Pydantic. Пример вы увидите ниже.
@@ -75,7 +75,7 @@ FastAPI будет использовать этот `response_model` для д
Чтобы использовать `EmailStr`, сначала установите <a href="https://github.com/JoshData/python-email-validator" class="external-link" target="_blank">`email-validator`</a>.
Убедитесь, что вы создали [виртуальное окружение](../virtual-environments.md){.internal-link target=_blank}, активировали его, а затем установите пакет, например:
Создайте [виртуальное окружение](../virtual-environments.md){.internal-link target=_blank}, активируйте его и затем установите пакет, например:
```console
$ pip install email-validator
@@ -105,7 +105,7 @@ $ pip install "pydantic[email]"
///
## Добавить выходную модель { #add-an-output-model }
## Добавить модель для ответа { #add-an-output-model }
Вместо этого мы можем создать входную модель с паролем в открытом виде и выходную модель без него:
@@ -123,7 +123,7 @@ $ pip install "pydantic[email]"
### `response_model` или возвращаемый тип { #response-model-or-return-type }
В этом случае, поскольку две модели различаются, если бы мы аннотировали возвращаемый тип функции как `UserOut`, редактор кода и инструменты пожаловались бы, что мы возвращаем неверный тип, так как это разные классы.
В этом случае, поскольку две модели различаются, если бы мы аннотировали возвращаемый тип функции как `UserOut`, редактор и инструменты пожаловались бы, что мы возвращаем неверный тип, так как это разные классы.
Поэтому в этом примере мы должны объявить тип ответа в параметре `response_model`.
@@ -135,33 +135,33 @@ $ pip install "pydantic[email]"
Мы хотим, чтобы FastAPI продолжал **фильтровать** данные с помощью модели ответа. Так что, даже если функция возвращает больше данных, в ответ будут включены только поля, объявленные в модели ответа.
В предыдущем примере, поскольку классы были разными, нам пришлось использовать параметр `response_model`. Но это также означает, что мы теряем поддержку от редактора кода и инструментов, проверяющих возвращаемый тип функции.
В предыдущем примере, поскольку классы были разными, нам пришлось использовать параметр `response_model`. Но это также означает, что мы теряем поддержку от редактора и инструментов, проверяющих возвращаемый тип функции.
Однако в большинстве таких случаев нам нужно лишь **отфильтровать/убрать** некоторые данные, как в этом примере.
И в этих случаях мы можем использовать классы и наследование, чтобы воспользоваться **аннотациями типов** функций для лучшей поддержки в редакторе кода и инструментах и при этом получить **фильтрацию данных** от FastAPI.
И в этих случаях мы можем использовать классы и наследование, чтобы воспользоваться **аннотациями типов** функций для лучшей поддержки в редакторе и инструментах и при этом получить **фильтрацию данных** от FastAPI.
{* ../../docs_src/response_model/tutorial003_01_py310.py hl[7:10,13:14,18] *}
Так мы получаем поддержку инструментов редакторов кода и mypy, так как этот код корректен с точки зрения типов — и одновременно получаем фильтрацию данных от FastAPI.
Так мы получаем поддержку инструментов (редакторы, mypy) — код корректен с точки зрения типов — и одновременно получаем фильтрацию данных от FastAPI.
Как это работает? Давайте разберёмся. 🤓
### Аннотации типов и инструменты { #type-annotations-and-tooling }
Сначала посмотрим, как это увидят редактор кода, mypy и другие инструменты.
Сначала посмотрим, как это увидят редакторы, mypy и другие инструменты.
`BaseUser` содержит базовые поля. Затем `UserIn` наследуется от `BaseUser` и добавляет поле `password`, то есть он будет включать все поля обеих моделей.
`BaseUser` содержит базовые поля. Затем `UserIn` наследуется от `BaseUser` и добавляет поле `password`, то есть он включает все поля обеих моделей.
Мы аннотируем возвращаемый тип функции как `BaseUser`, но фактически возвращаем экземпляр `UserIn`.
Редактор кода, mypy и другие инструменты не будут возражать, потому что с точки зрения типов `UserIn` — подкласс `BaseUser`, что означает, что это *валидный* тип везде, где ожидается что-то, являющееся `BaseUser`.
Редактор, mypy и другие инструменты не будут возражать, потому что с точки зрения типов `UserIn` — подкласс `BaseUser`, что означает, что это *валидный* тип везде, где ожидается что-то, являющееся `BaseUser`.
### Фильтрация данных FastAPI { #fastapi-data-filtering }
Теперь для FastAPI: он увидит возвращаемый тип и убедится, что то, что вы возвращаете, включает **только** поля, объявленные в этом типе.
Теперь, для FastAPI: он увидит возвращаемый тип и убедится, что то, что вы возвращаете, включает **только** поля, объявленные в этом типе.
FastAPI делает несколько вещей внутри вместе с Pydantic, чтобы гарантировать, что те же правила наследования классов не используются для фильтрации возвращаемых данных, иначе вы могли бы в итоге вернуть намного больше данных, чем ожидали.
FastAPI делает несколько вещей внутри вместе с Pydantic, чтобы гарантировать, что те же правила наследования классов не используются для фильтрации возвращаемых данных, иначе вы могли бы вернуть гораздо больше данных, чем ожидали.
Таким образом вы получаете лучшее из обоих миров: аннотации типов с **поддержкой инструментов** и **фильтрацию данных**.
@@ -171,17 +171,17 @@ FastAPI делает несколько вещей внутри вместе с
<img src="/img/tutorial/response-model/image01.png">
И обе модели будут использоваться в интерактивной документации API:
И обе модели используются в интерактивной документации API:
<img src="/img/tutorial/response-model/image02.png">
## Другие аннотации возвращаемых типов { #other-return-type-annotations }
Бывают случаи, когда вы возвращаете что-то, что не является валидным полем Pydantic, и аннотируете это в функции только ради поддержки инструментов (редактор кода, mypy и т.д.).
Бывают случаи, когда вы возвращаете что-то, что не является валидным полем Pydantic, и аннотируете это в функции только ради поддержки инструментов (редактор, mypy и т. д.).
### Возврат Response напрямую { #return-a-response-directly }
Самый распространённый случай — [возвращать Response напрямую, как описано далее в разделах документации для продвинутых](../advanced/response-directly.md){.internal-link target=_blank}.
Самый распространённый случай — [возвращать Response напрямую, как описано далее в разделах для продвинутых](../advanced/response-directly.md){.internal-link target=_blank}.
{* ../../docs_src/response_model/tutorial003_02_py39.py hl[8,10:11] *}
@@ -195,7 +195,7 @@ FastAPI делает несколько вещей внутри вместе с
{* ../../docs_src/response_model/tutorial003_03_py39.py hl[8:9] *}
Это тоже сработает, так как `RedirectResponse` — подкласс `Response`, и FastAPI автоматически обработает этот простой случай.
Это тоже сработает, так как `RedirectResponse` — подкласс `Response`, и FastAPI автоматически обработает этот случай.
### Некорректные аннотации возвращаемых типов { #invalid-return-type-annotations }
@@ -209,15 +209,15 @@ FastAPI делает несколько вещей внутри вместе с
### Отключить модель ответа { #disable-response-model }
Продолжая пример выше, вы можете не хотеть использовать стандартные валидацию данных, документирование, фильтрацию и т.п., выполняемые FastAPI.
Продолжая пример выше, вы можете не хотеть использовать стандартную валидацию данных, документацию, фильтрацию и т.д., выполняемые FastAPI.
Но при этом вы можете хотеть сохранить аннотацию возвращаемого типа в функции, чтобы пользоваться поддержкой инструментов вроде редакторов кода и инструментов проверки типов (например, mypy).
Но при этом вы можете хотеть сохранить аннотацию возвращаемого типа в функции, чтобы пользоваться поддержкой инструментов (редакторы, проверки типов вроде mypy).
В этом случае вы можете отключить генерацию модели ответа, установив `response_model=None`:
{* ../../docs_src/response_model/tutorial003_05_py310.py hl[7] *}
Так FastAPI пропустит генерацию модели ответа, и вы сможете использовать любые аннотации возвращаемых типов, которые вам нужны, без влияния на ваше приложение FastAPI. 🤓
Так FastAPI пропустит генерацию модели ответа, и вы сможете использовать любые аннотации возвращаемых типов, не влияя на ваше приложение FastAPI. 🤓
## Параметры кодирования модели ответа { #response-model-encoding-parameters }
@@ -252,6 +252,20 @@ FastAPI делает несколько вещей внутри вместе с
/// info | Информация
В Pydantic v1 метод назывался `.dict()`, в Pydantic v2 он был помечен как устаревший (но всё ещё поддерживается) и переименован в `.model_dump()`.
Примеры здесь используют `.dict()` для совместимости с Pydantic v1, но если вы используете Pydantic v2, применяйте `.model_dump()`.
///
/// info | Информация
FastAPI использует метод `.dict()` у Pydantic-моделей с <a href="https://docs.pydantic.dev/1.10/usage/exporting_models/#modeldict" class="external-link" target="_blank">параметром `exclude_unset`</a>, чтобы добиться такого поведения.
///
/// info | Информация
Вы также можете использовать:
* `response_model_exclude_defaults=True`
@@ -298,7 +312,7 @@ FastAPI достаточно умен (на самом деле, это Pydantic
Обратите внимание, что значения по умолчанию могут быть любыми, не только `None`.
Это может быть список (`[]`), число с плавающей точкой `10.5` и т.д.
Это может быть список (`[]`), число с плавающей точкой `10.5` и т. д.
///
@@ -332,7 +346,7 @@ FastAPI достаточно умен (на самом деле, это Pydantic
#### Использование `list` вместо `set` { #using-lists-instead-of-sets }
Если вы забыли использовать `set` и применили `list` или `tuple` вместо него, FastAPI всё равно преобразует это в `set`, и всё будет работать корректно:
Если вы забыли использовать `set` и применили `list` или `tuple`, FastAPI всё равно преобразует это в `set`, и всё будет работать корректно:
{* ../../docs_src/response_model/tutorial006_py310.py hl[29,35] *}

View File

@@ -8,14 +8,36 @@
Вы можете объявить `examples` для модели Pydantic, которые будут добавлены в сгенерированную JSON Schema.
//// tab | Pydantic v2
{* ../../docs_src/schema_extra_example/tutorial001_py310.py hl[13:24] *}
////
//// tab | Pydantic v1
{* ../../docs_src/schema_extra_example/tutorial001_pv1_py310.py hl[13:23] *}
////
Эта дополнительная информация будет добавлена как есть в выходную **JSON Schema** этой модели и будет использоваться в документации API.
Вы можете использовать атрибут `model_config`, который принимает `dict`, как описано в <a href="https://docs.pydantic.dev/latest/api/config/" class="external-link" target="_blank">Документации Pydantic: Конфигурация</a>.
//// tab | Pydantic v2
В Pydantic версии 2 вы будете использовать атрибут `model_config`, который принимает `dict`, как описано в <a href="https://docs.pydantic.dev/latest/api/config/" class="external-link" target="_blank">Документации Pydantic: Конфигурация</a>.
Вы можете задать `"json_schema_extra"` с `dict`, содержащим любые дополнительные данные, которые вы хотите видеть в сгенерированной JSON Schema, включая `examples`.
////
//// tab | Pydantic v1
В Pydantic версии 1 вы будете использовать внутренний класс `Config` и `schema_extra`, как описано в <a href="https://docs.pydantic.dev/1.10/usage/schema/#schema-customization" class="external-link" target="_blank">Документации Pydantic: Настройка схемы</a>.
Вы можете задать `schema_extra` со `dict`, содержащим любые дополнительные данные, которые вы хотите видеть в сгенерированной JSON Schema, включая `examples`.
////
/// tip | Подсказка
Вы можете использовать тот же приём, чтобы расширить JSON Schema и добавить свою собственную дополнительную информацию.
@@ -102,7 +124,7 @@ OpenAPI 3.1.0 (используется начиная с FastAPI 0.99.0) доб
Ключи `dict` идентифицируют каждый пример, а каждое значение — это ещё один `dict`.
Каждый конкретный пример `dict` в `examples` может содержать:
Каждый конкретный пример`dict` в `examples` может содержать:
* `summary`: Краткое описание примера.
* `description`: Подробное описание, которое может содержать текст в Markdown.
@@ -113,7 +135,7 @@ OpenAPI 3.1.0 (используется начиная с FastAPI 0.99.0) доб
{* ../../docs_src/schema_extra_example/tutorial005_an_py310.py hl[23:49] *}
### OpenAPI-примеры в UI документации { #openapi-examples-in-the-docs-ui }
### OpenAPI-примеры в UI документации { #openapi-examples-in-the-docs-ui }
С `openapi_examples`, добавленным в `Body()`, страница `/docs` будет выглядеть так:
@@ -191,7 +213,7 @@ OpenAPI также добавила поля `example` и `examples` в друг
### Swagger UI и специфичные для OpenAPI `examples` { #swagger-ui-and-openapi-specific-examples }
Теперь, поскольку Swagger UI не поддерживал несколько примеров JSON Schema (по состоянию на 2023-08-26), у пользователей не было способа показать несколько примеров в документации.
Раньше, поскольку Swagger UI не поддерживал несколько примеров JSON Schema (по состоянию на 2023-08-26), у пользователей не было способа показать несколько примеров в документации.
Чтобы решить это, FastAPI `0.103.0` **добавил поддержку** объявления того же старого, **специфичного для OpenAPI**, поля `examples` с новым параметром `openapi_examples`. 🤓

View File

@@ -4,16 +4,10 @@ Translate to Turkish (Türkçe).
Language code: tr.
### Core principle
Don't translate word-by-word. Rewrite naturally in Turkish as if writing the doc from scratch. Preserve meaning, but prioritize fluency over literal accuracy.
### Grammar and tone
- Use instructional Turkish, consistent with existing Turkish docs.
- Use imperative/guide language (e.g. "açalım", "gidin", "kopyalayalım", "bir bakalım").
- Avoid filler words and overly long sentences.
- Ensure sentences make sense in Turkish context — adjust structure, conjunctions, and verb forms as needed for natural flow (e.g. use "Ancak" instead of "Ve" when connecting contrasting sentences, use "-maktadır/-mektedir" for formal statements).
- Use imperative/guide language when appropriate (e.g. açalım, gidin, kopyalayalım).
### Headings
@@ -21,23 +15,13 @@ Don't translate word-by-word. Rewrite naturally in Turkish as if writing the doc
### Quotes
- Keep quote style consistent with existing Turkish docs (typically ASCII quotes in text).
- Never modify quotes inside inline code, code blocks, URLs, or file paths.
- Alıntı stili mevcut Türkçe dokümanlarla tutarlı tutun (genellikle metin içinde ASCII tırnak işaretleri kullanılır).
- Satır içi kod, kod blokları, URL'ler veya dosya yolları içindeki tırnak işaretlerini asla değiştirmeyin.
### Ellipsis
- Keep ellipsis style (`...`) consistent with existing Turkish docs.
- Never modify `...` in code, URLs, or CLI examples.
### Consistency
- Use the same translation for the same term throughout the document.
- If you translate a concept one way, keep it consistent across all occurrences.
### Links and references
- Never modify link syntax like `{.internal-link target=_blank}`.
- Keep markdown link structure intact: `[text](url){.internal-link}`.
- Üç nokta (...) stili mevcut Türkçe dokümanlarla tutarlı tutun.
- Kod, URL veya CLI örneklerindeki `...` ifadesini asla değiştirmeyin.
### Preferred translations / glossary

View File

@@ -1,5 +1,5 @@
from a2wsgi import WSGIMiddleware
from fastapi import FastAPI
from fastapi.middleware.wsgi import WSGIMiddleware
from flask import Flask, request
from markupsafe import escape

View File

@@ -1,3 +1 @@
from starlette.middleware.wsgi import (
WSGIMiddleware as WSGIMiddleware,
) # pragma: no cover # noqa
from starlette.middleware.wsgi import WSGIMiddleware as WSGIMiddleware # noqa

View File

@@ -178,7 +178,6 @@ tests = [
"strawberry-graphql>=0.200.0,<1.0.0",
"types-orjson==3.6.2",
"types-ujson==5.10.0.20240515",
"a2wsgi>=1.9.0,<=2.0.0",
]
translations = [
"gitpython==3.1.45",

16
uv.lock generated
View File

@@ -7,18 +7,6 @@ resolution-markers = [
"python_full_version < '3.10'",
]
[[package]]
name = "a2wsgi"
version = "1.10.10"
source = { registry = "https://pypi.org/simple" }
dependencies = [
{ name = "typing-extensions", marker = "python_full_version < '3.11'" },
]
sdist = { url = "https://files.pythonhosted.org/packages/9a/cb/822c56fbea97e9eee201a2e434a80437f6750ebcb1ed307ee3a0a7505b14/a2wsgi-1.10.10.tar.gz", hash = "sha256:a5bcffb52081ba39df0d5e9a884fc6f819d92e3a42389343ba77cbf809fe1f45", size = 18799, upload-time = "2025-06-18T09:00:10.843Z" }
wheels = [
{ url = "https://files.pythonhosted.org/packages/02/d5/349aba3dc421e73cbd4958c0ce0a4f1aa3a738bc0d7de75d2f40ed43a535/a2wsgi-1.10.10-py3-none-any.whl", hash = "sha256:d2b21379479718539dc15fce53b876251a0efe7615352dfe49f6ad1bc507848d", size = 17389, upload-time = "2025-06-18T09:00:09.676Z" },
]
[[package]]
name = "ag-ui-protocol"
version = "0.1.10"
@@ -1070,7 +1058,6 @@ standard-no-fastapi-cloud-cli = [
[package.dev-dependencies]
dev = [
{ name = "a2wsgi" },
{ name = "anyio", extra = ["trio"] },
{ name = "black" },
{ name = "cairosvg" },
@@ -1144,7 +1131,6 @@ github-actions = [
{ name = "smokeshow" },
]
tests = [
{ name = "a2wsgi" },
{ name = "anyio", extra = ["trio"] },
{ name = "coverage", version = "7.10.7", source = { registry = "https://pypi.org/simple" }, extra = ["toml"], marker = "python_full_version < '3.10'" },
{ name = "coverage", version = "7.13.1", source = { registry = "https://pypi.org/simple" }, extra = ["toml"], marker = "python_full_version >= '3.10'" },
@@ -1211,7 +1197,6 @@ provides-extras = ["standard", "standard-no-fastapi-cloud-cli", "all"]
[package.metadata.requires-dev]
dev = [
{ name = "a2wsgi", specifier = ">=1.9.0,<=2.0.0" },
{ name = "anyio", extras = ["trio"], specifier = ">=3.2.1,<5.0.0" },
{ name = "black", specifier = "==25.1.0" },
{ name = "cairosvg", specifier = "==2.8.2" },
@@ -1281,7 +1266,6 @@ github-actions = [
{ name = "smokeshow", specifier = ">=0.5.0" },
]
tests = [
{ name = "a2wsgi", specifier = ">=1.9.0,<=2.0.0" },
{ name = "anyio", extras = ["trio"], specifier = ">=3.2.1,<5.0.0" },
{ name = "coverage", extras = ["toml"], specifier = ">=6.5.0,<8.0" },
{ name = "dirty-equals", specifier = "==0.9.0" },