mirror of https://github.com/tiangolo/fastapi.git
📝 Update docs, typos, aclarations, fix examples
for NoSQL models
This commit is contained in:
parent
2a48b10be3
commit
659b8ae8af
|
|
@ -61,15 +61,14 @@ second_user_data = {
|
||||||
"joined": "2018-11-30",
|
"joined": "2018-11-30",
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
# **second_user_data means:
|
|
||||||
# pass the keys and values of the dict
|
|
||||||
# directly as key-value arguments
|
|
||||||
# equivalent to:
|
|
||||||
# id=4, name="Mary", joined="2018-11-30"
|
|
||||||
my_second_user: User = User(**second_user_data)
|
my_second_user: User = User(**second_user_data)
|
||||||
```
|
```
|
||||||
|
|
||||||
|
!!! info
|
||||||
|
`**second_user_data` means:
|
||||||
|
|
||||||
|
Pass the keys and values of the `second_user_data` dict directly as key-value arguments, equivalent to: `User(id=4, name="Mary", joined="2018-11-30")`
|
||||||
|
|
||||||
### Editor support
|
### Editor support
|
||||||
|
|
||||||
All the framework was designed to be easy and intuitive to use, all the decisons where tested on multiple editors even before starting development, to ensure the best development experience.
|
All the framework was designed to be easy and intuitive to use, all the decisons where tested on multiple editors even before starting development, to ensure the best development experience.
|
||||||
|
|
|
||||||
|
|
@ -76,7 +76,7 @@ And you can declare dependencies with `async def` inside of normal `def` path op
|
||||||
It doesn't matter. **FastAPI** will know what to do.
|
It doesn't matter. **FastAPI** will know what to do.
|
||||||
|
|
||||||
!!! note
|
!!! note
|
||||||
If you don't if you should use `async def` or not, check the section about [`async` and `await` in the docs](/tutorial/async.md).
|
If you don't know, check the _"In a hurry?"_ section about <a href="https://fastapi.tiangolo.com/async/#in-a-hurry" target="_blank">`async` and `await` in the docs</a>.
|
||||||
|
|
||||||
## Integrated wiht OpenAPI
|
## Integrated wiht OpenAPI
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -2,9 +2,9 @@ This tutorial shows you how to use **FastAPI** with all its features, step by st
|
||||||
|
|
||||||
Eeach section gradually builds on the previous ones, but it's structured to separate topics, so that you can go directly to any specific one to solve your specific API needs.
|
Eeach section gradually builds on the previous ones, but it's structured to separate topics, so that you can go directly to any specific one to solve your specific API needs.
|
||||||
|
|
||||||
It is also built to work as a future reference. So you can come back and see exactly what you need.
|
It is also built to work as a future reference.
|
||||||
|
|
||||||
And each section is very short, so you can go directly to what you need and get the information fast.
|
So you can come back and see exactly what you need.
|
||||||
|
|
||||||
## Run the code
|
## Run the code
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -43,11 +43,13 @@ In the code, a `Bucket` represents the main entrypoint of communication with the
|
||||||
This utility function will:
|
This utility function will:
|
||||||
|
|
||||||
* Connect to a **Couchbase** cluster (that might be a single machine).
|
* Connect to a **Couchbase** cluster (that might be a single machine).
|
||||||
|
* Set defaults for timeouts.
|
||||||
* Authenticate in the cluster.
|
* Authenticate in the cluster.
|
||||||
* Get a `Bucket` instance.
|
* Get a `Bucket` instance.
|
||||||
|
* Set defaults for timeouts.
|
||||||
* Return it.
|
* Return it.
|
||||||
|
|
||||||
```Python hl_lines="13 14 15 16 17 18"
|
```Python hl_lines="13 14 15 16 17 18 19 20"
|
||||||
{!./tutorial/src/nosql-databases/tutorial001.py!}
|
{!./tutorial/src/nosql-databases/tutorial001.py!}
|
||||||
```
|
```
|
||||||
|
|
||||||
|
|
@ -59,7 +61,7 @@ As **Couchbase** "documents" are actually just "JSON objects", we can model them
|
||||||
|
|
||||||
First, let's create a `User` model:
|
First, let's create a `User` model:
|
||||||
|
|
||||||
```Python hl_lines="21 22 23 24 25"
|
```Python hl_lines="23 24 25 26 27"
|
||||||
{!./tutorial/src/nosql-databases/tutorial001.py!}
|
{!./tutorial/src/nosql-databases/tutorial001.py!}
|
||||||
```
|
```
|
||||||
|
|
||||||
|
|
@ -71,28 +73,12 @@ Now, let's create a `UserInDB` model.
|
||||||
|
|
||||||
This will have the data that is actually stored in the database.
|
This will have the data that is actually stored in the database.
|
||||||
|
|
||||||
In Couchbase, each document has a document <abbr title="Identification">ID</abbr> or "key".
|
We don't create it as a subclass of Pydantic's `BaseModel` but as a subclass of our own `User`, because it will have all the attributes in `User` plus a couple more:
|
||||||
|
|
||||||
But it is not part of the document itself.
|
```Python hl_lines="30 31 32"
|
||||||
|
|
||||||
It is stored as "metadata" of the document.
|
|
||||||
|
|
||||||
So, to be able to have that document ID as part of our model without it being part of the attributes (document contents), we can do a simple trick.
|
|
||||||
|
|
||||||
We can create an internal `class`, in this case named `Meta`, and declare the extra attribute(s) in that class.
|
|
||||||
|
|
||||||
This class doesn't have any special meaning and doesn't provide any special functionality other than not being directly an attribute of our main model:
|
|
||||||
|
|
||||||
```Python hl_lines="28 29 30 31 32 33"
|
|
||||||
{!./tutorial/src/nosql-databases/tutorial001.py!}
|
{!./tutorial/src/nosql-databases/tutorial001.py!}
|
||||||
```
|
```
|
||||||
|
|
||||||
This `Meta` class won't be included when we generate a `dict` from our model, but we will be able to access it's data with something like:
|
|
||||||
|
|
||||||
```Python
|
|
||||||
my_user.Meta.key
|
|
||||||
```
|
|
||||||
|
|
||||||
!!! note
|
!!! note
|
||||||
Notice that we have a `hashed_password` and a `type` field that will be stored in the database.
|
Notice that we have a `hashed_password` and a `type` field that will be stored in the database.
|
||||||
|
|
||||||
|
|
@ -107,11 +93,10 @@ Now create a function that will:
|
||||||
* Generate a document ID from it.
|
* Generate a document ID from it.
|
||||||
* Get the document with that ID.
|
* Get the document with that ID.
|
||||||
* Put the contents of the document in a `UserInDB` model.
|
* Put the contents of the document in a `UserInDB` model.
|
||||||
* Add the extracted document `key` to our model.
|
|
||||||
|
|
||||||
By creating a function that is only dedicated to getting your user from a `username` (or any other parameter) independent of your path operation function, you can more easily re-use it in multiple parts and also add <abbr title="Automated test, written in code, that checks if another piece of code is working correctly.">unit tests</abbr> for it:
|
By creating a function that is only dedicated to getting your user from a `username` (or any other parameter) independent of your path operation function, you can more easily re-use it in multiple parts and also add <abbr title="Automated test, written in code, that checks if another piece of code is working correctly.">unit tests</abbr> for it:
|
||||||
|
|
||||||
```Python hl_lines="36 37 38 39 40 41 42 43"
|
```Python hl_lines="35 36 37 38 39 40 41"
|
||||||
{!./tutorial/src/nosql-databases/tutorial001.py!}
|
{!./tutorial/src/nosql-databases/tutorial001.py!}
|
||||||
```
|
```
|
||||||
|
|
||||||
|
|
@ -146,7 +131,7 @@ UserInDB(username="johndoe", hashed_password="some_hash")
|
||||||
|
|
||||||
### Create the `FastAPI` app
|
### Create the `FastAPI` app
|
||||||
|
|
||||||
```Python hl_lines="47"
|
```Python hl_lines="45"
|
||||||
{!./tutorial/src/nosql-databases/tutorial001.py!}
|
{!./tutorial/src/nosql-databases/tutorial001.py!}
|
||||||
```
|
```
|
||||||
|
|
||||||
|
|
@ -156,7 +141,7 @@ As our code is calling Couchbase and we are not using the <a href="https://docs.
|
||||||
|
|
||||||
Also, Couchbase recommends not using a single `Bucket` object in multiple "<abbr title="A sequence of code being executed by the program, while at the same time, or at intervals, there can be others being executed too.">thread</abbr>s", so, we can get just get the bucket directly and pass it to our utility functions:
|
Also, Couchbase recommends not using a single `Bucket` object in multiple "<abbr title="A sequence of code being executed by the program, while at the same time, or at intervals, there can be others being executed too.">thread</abbr>s", so, we can get just get the bucket directly and pass it to our utility functions:
|
||||||
|
|
||||||
```Python hl_lines="50 51 52 53 54"
|
```Python hl_lines="48 49 50 51 52"
|
||||||
{!./tutorial/src/nosql-databases/tutorial001.py!}
|
{!./tutorial/src/nosql-databases/tutorial001.py!}
|
||||||
```
|
```
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -96,7 +96,7 @@ All the data validation is performed under the hood by <a href="https://pydantic
|
||||||
|
|
||||||
You can use the same type declarations with `str`, `float`, `bool` and many other complex data types.
|
You can use the same type declarations with `str`, `float`, `bool` and many other complex data types.
|
||||||
|
|
||||||
These are explored in the next sections of the tutorial.
|
These are explored in the next chapters of the tutorial.
|
||||||
|
|
||||||
## Recap
|
## Recap
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -199,4 +199,4 @@ Validations specific for strings:
|
||||||
|
|
||||||
In these examples you saw how to declare validations for `str` values.
|
In these examples you saw how to declare validations for `str` values.
|
||||||
|
|
||||||
See the next sections to see how to declare validations for other types, like numbers.
|
See the next chapters to see how to declare validations for other types, like numbers.
|
||||||
|
|
@ -11,10 +11,12 @@ USERPROFILE_DOC_TYPE = "userprofile"
|
||||||
|
|
||||||
|
|
||||||
def get_bucket():
|
def get_bucket():
|
||||||
cluster = Cluster("couchbase://couchbasehost:8091")
|
cluster = Cluster("couchbase://couchbasehost:8091?fetch_mutation_tokens=1&operation_timeout=30&n1ql_timeout=300")
|
||||||
authenticator = PasswordAuthenticator("username", "password")
|
authenticator = PasswordAuthenticator("username", "password")
|
||||||
cluster.authenticate(authenticator)
|
cluster.authenticate(authenticator)
|
||||||
bucket: Bucket = cluster.open_bucket("bucket_name", lockmode=LOCKMODE_WAIT)
|
bucket: Bucket = cluster.open_bucket("bucket_name", lockmode=LOCKMODE_WAIT)
|
||||||
|
bucket.timeout = 30
|
||||||
|
bucket.n1ql_timeout = 300
|
||||||
return bucket
|
return bucket
|
||||||
|
|
||||||
|
|
||||||
|
|
@ -29,9 +31,6 @@ class UserInDB(User):
|
||||||
type: str = USERPROFILE_DOC_TYPE
|
type: str = USERPROFILE_DOC_TYPE
|
||||||
hashed_password: str
|
hashed_password: str
|
||||||
|
|
||||||
class Meta:
|
|
||||||
key: Optional[str] = None
|
|
||||||
|
|
||||||
|
|
||||||
def get_user(bucket: Bucket, username: str):
|
def get_user(bucket: Bucket, username: str):
|
||||||
doc_id = f"userprofile::{username}"
|
doc_id = f"userprofile::{username}"
|
||||||
|
|
@ -39,7 +38,6 @@ def get_user(bucket: Bucket, username: str):
|
||||||
if not result.value:
|
if not result.value:
|
||||||
return None
|
return None
|
||||||
user = UserInDB(**result.value)
|
user = UserInDB(**result.value)
|
||||||
user.Meta.key = result.key
|
|
||||||
return user
|
return user
|
||||||
|
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -1,4 +1,4 @@
|
||||||
from typing import Tuple, Set
|
from typing import Set, Tuple
|
||||||
|
|
||||||
|
|
||||||
def process_items(items_t: Tuple[int], items_s: Set[bytes]):
|
def process_items(items_t: Tuple[int], items_s: Set[bytes]):
|
||||||
|
|
|
||||||
|
|
@ -4,4 +4,4 @@ class Person:
|
||||||
|
|
||||||
|
|
||||||
def get_person_name(one_person: Person):
|
def get_person_name(one_person: Person):
|
||||||
return one_person.name
|
return one_person.name
|
||||||
|
|
|
||||||
|
|
@ -1,14 +1,21 @@
|
||||||
from datetime import datetime
|
from datetime import datetime
|
||||||
from typing import List
|
from typing import List
|
||||||
|
|
||||||
from pydantic import BaseModel
|
from pydantic import BaseModel
|
||||||
|
|
||||||
|
|
||||||
class User(BaseModel):
|
class User(BaseModel):
|
||||||
id: int
|
id: int
|
||||||
name = 'John Doe'
|
name = "John Doe"
|
||||||
signup_ts: datetime = None
|
signup_ts: datetime = None
|
||||||
friends: List[int] = []
|
friends: List[int] = []
|
||||||
|
|
||||||
external_data = {'id': '123', 'signup_ts': '2017-06-01 12:22', 'friends': [1, '2', b'3']}
|
|
||||||
|
external_data = {
|
||||||
|
"id": "123",
|
||||||
|
"signup_ts": "2017-06-01 12:22",
|
||||||
|
"friends": [1, "2", b"3"],
|
||||||
|
}
|
||||||
user = User(**external_data)
|
user = User(**external_data)
|
||||||
print(user)
|
print(user)
|
||||||
# > User id=123 name='John Doe' signup_ts=datetime.datetime(2017, 6, 1, 12, 22) friends=[1, 2, 3]
|
# > User id=123 name='John Doe' signup_ts=datetime.datetime(2017, 6, 1, 12, 22) friends=[1, 2, 3]
|
||||||
|
|
|
||||||
|
|
@ -14,7 +14,7 @@ repo_url: https://github.com/tiangolo/fastapi
|
||||||
edit_uri: ""
|
edit_uri: ""
|
||||||
|
|
||||||
nav:
|
nav:
|
||||||
- Introduction: 'index.md'
|
- FastAPI: 'index.md'
|
||||||
- Features: 'features.md'
|
- Features: 'features.md'
|
||||||
- Tutorial - User Guide:
|
- Tutorial - User Guide:
|
||||||
- Tutorial - User Guide - Intro: 'tutorial/intro.md'
|
- Tutorial - User Guide - Intro: 'tutorial/intro.md'
|
||||||
|
|
|
||||||
Loading…
Reference in New Issue