diff --git a/docs/tutorial/src/tutorial34.py b/docs/tutorial/src/tutorial34.py new file mode 100644 index 000000000..6c8b101ba --- /dev/null +++ b/docs/tutorial/src/tutorial34.py @@ -0,0 +1,17 @@ +from fastapi import Body, FastAPI +from pydantic import BaseModel, Schema + +app = FastAPI() + + +class Item(BaseModel): + name: str + description: str = Schema(None, title="The description of the item", max_length=300) + price: float = Schema(..., gt=0, description="The price must be greater than zero") + tax: float = None + + +@app.put("/items/{item_id}") +async def update_item(*, item_id: int, item: Item = Body(..., embed=True)): + results = {"item_id": item_id, "item": item} + return results diff --git a/docs/tutorial/src/tutorial35.py b/docs/tutorial/src/tutorial35.py index 9e0fa4494..3f4f53265 100644 --- a/docs/tutorial/src/tutorial35.py +++ b/docs/tutorial/src/tutorial35.py @@ -1,5 +1,5 @@ -from fastapi import FastAPI -from pydantic import BaseModel +from fastapi import Body, FastAPI +from pydantic import BaseModel, Schema app = FastAPI() @@ -9,10 +9,21 @@ class Item(BaseModel): description: str = None price: float tax: float = None - tags: list = [] @app.put("/items/{item_id}") -async def update_item(*, item_id: int, item: Item): +async def update_item( + *, + item_id: int, + item: Item = Body( + ..., + example={ + "name": "Foo", + "description": "A very nice Item", + "price": 35.4, + "tax": 3.2, + }, + ) +): results = {"item_id": item_id, "item": item} return results diff --git a/docs/tutorial/src/tutorial36.py b/docs/tutorial/src/tutorial36.py index 8f769279b..9e0fa4494 100644 --- a/docs/tutorial/src/tutorial36.py +++ b/docs/tutorial/src/tutorial36.py @@ -1,5 +1,3 @@ -from typing import List - from fastapi import FastAPI from pydantic import BaseModel @@ -11,7 +9,7 @@ class Item(BaseModel): description: str = None price: float tax: float = None - tags: List[str] = [] + tags: list = [] @app.put("/items/{item_id}") diff --git a/docs/tutorial/src/tutorial37.py b/docs/tutorial/src/tutorial37.py index 291b3c64d..8f769279b 100644 --- a/docs/tutorial/src/tutorial37.py +++ b/docs/tutorial/src/tutorial37.py @@ -1,4 +1,4 @@ -from typing import Set +from typing import List from fastapi import FastAPI from pydantic import BaseModel @@ -11,7 +11,7 @@ class Item(BaseModel): description: str = None price: float tax: float = None - tags: Set[str] = [] + tags: List[str] = [] @app.put("/items/{item_id}") diff --git a/docs/tutorial/src/tutorial38.py b/docs/tutorial/src/tutorial38.py index 257928ef3..291b3c64d 100644 --- a/docs/tutorial/src/tutorial38.py +++ b/docs/tutorial/src/tutorial38.py @@ -6,18 +6,12 @@ from pydantic import BaseModel app = FastAPI() -class Image(BaseModel): - url: str - name: str - - class Item(BaseModel): name: str description: str = None price: float tax: float = None tags: Set[str] = [] - image: Image = None @app.put("/items/{item_id}") diff --git a/docs/tutorial/src/tutorial39.py b/docs/tutorial/src/tutorial39.py index f5f19b390..257928ef3 100644 --- a/docs/tutorial/src/tutorial39.py +++ b/docs/tutorial/src/tutorial39.py @@ -2,13 +2,12 @@ from typing import Set from fastapi import FastAPI from pydantic import BaseModel -from pydantic.types import UrlStr app = FastAPI() class Image(BaseModel): - url: UrlStr + url: str name: str diff --git a/docs/tutorial/src/tutorial40.py b/docs/tutorial/src/tutorial40.py index 09d8be768..f5f19b390 100644 --- a/docs/tutorial/src/tutorial40.py +++ b/docs/tutorial/src/tutorial40.py @@ -1,4 +1,4 @@ -from typing import List, Set +from typing import Set from fastapi import FastAPI from pydantic import BaseModel @@ -18,7 +18,7 @@ class Item(BaseModel): price: float tax: float = None tags: Set[str] = [] - image: List[Image] = None + image: Image = None @app.put("/items/{item_id}") diff --git a/docs/tutorial/src/tutorial41.py b/docs/tutorial/src/tutorial41.py index cda802d3e..09d8be768 100644 --- a/docs/tutorial/src/tutorial41.py +++ b/docs/tutorial/src/tutorial41.py @@ -21,13 +21,7 @@ class Item(BaseModel): image: List[Image] = None -class Offer(BaseModel): - name: str - description: str = None - price: float - items: List[Item] - - -@app.post("/offers/") -async def create_offer(*, offer: Offer): - return offer +@app.put("/items/{item_id}") +async def update_item(*, item_id: int, item: Item): + results = {"item_id": item_id, "item": item} + return results diff --git a/docs/tutorial/src/tutorial42.py b/docs/tutorial/src/tutorial42.py index 34b868563..cda802d3e 100644 --- a/docs/tutorial/src/tutorial42.py +++ b/docs/tutorial/src/tutorial42.py @@ -1,4 +1,4 @@ -from typing import List +from typing import List, Set from fastapi import FastAPI from pydantic import BaseModel @@ -12,6 +12,22 @@ class Image(BaseModel): name: str -@app.post("/images/multiple/") -async def create_multiple_images(*, images: List[Image]): - return images +class Item(BaseModel): + name: str + description: str = None + price: float + tax: float = None + tags: Set[str] = [] + image: List[Image] = None + + +class Offer(BaseModel): + name: str + description: str = None + price: float + items: List[Item] + + +@app.post("/offers/") +async def create_offer(*, offer: Offer): + return offer diff --git a/docs/tutorial/src/tutorial43.py b/docs/tutorial/src/tutorial43.py index 5a6fd30fe..34b868563 100644 --- a/docs/tutorial/src/tutorial43.py +++ b/docs/tutorial/src/tutorial43.py @@ -1,8 +1,17 @@ -from fastapi import Cookie, FastAPI +from typing import List + +from fastapi import FastAPI +from pydantic import BaseModel +from pydantic.types import UrlStr app = FastAPI() -@app.get("/items/") -async def read_items(*, ads_id: str = Cookie(None)): - return {"ads_id": ads_id} +class Image(BaseModel): + url: UrlStr + name: str + + +@app.post("/images/multiple/") +async def create_multiple_images(*, images: List[Image]): + return images diff --git a/docs/tutorial/src/tutorial44.py b/docs/tutorial/src/tutorial44.py index 24a59e530..5a6fd30fe 100644 --- a/docs/tutorial/src/tutorial44.py +++ b/docs/tutorial/src/tutorial44.py @@ -1,8 +1,8 @@ -from fastapi import FastAPI, Header +from fastapi import Cookie, FastAPI app = FastAPI() @app.get("/items/") -async def read_items(*, accept_encoding: str = Header(None)): - return {"Accept-Encoding": accept_encoding} +async def read_items(*, ads_id: str = Cookie(None)): + return {"ads_id": ads_id} diff --git a/docs/tutorial/src/tutorial45.py b/docs/tutorial/src/tutorial45.py index 4edc4b6fd..24a59e530 100644 --- a/docs/tutorial/src/tutorial45.py +++ b/docs/tutorial/src/tutorial45.py @@ -4,5 +4,5 @@ app = FastAPI() @app.get("/items/") -async def read_items(*, strange_header: str = Header(None, convert_underscores=False)): - return {"strange_header": strange_header} +async def read_items(*, accept_encoding: str = Header(None)): + return {"Accept-Encoding": accept_encoding} diff --git a/docs/tutorial/src/tutorial46.py b/docs/tutorial/src/tutorial46.py index 86dadcbda..4edc4b6fd 100644 --- a/docs/tutorial/src/tutorial46.py +++ b/docs/tutorial/src/tutorial46.py @@ -1,19 +1,8 @@ -from typing import Set - -from fastapi import FastAPI -from pydantic import BaseModel +from fastapi import FastAPI, Header app = FastAPI() -class Item(BaseModel): - name: str - description: str = None - price: float - tax: float = None - tags: Set[str] = [] - - -@app.post("/items/", response_model=Item) -async def create_item(*, item: Item): - return item +@app.get("/items/") +async def read_items(*, strange_header: str = Header(None, convert_underscores=False)): + return {"strange_header": strange_header} diff --git a/docs/tutorial/src/tutorial47.py b/docs/tutorial/src/tutorial47.py index 3fb475b9d..86dadcbda 100644 --- a/docs/tutorial/src/tutorial47.py +++ b/docs/tutorial/src/tutorial47.py @@ -1,18 +1,19 @@ +from typing import Set + from fastapi import FastAPI from pydantic import BaseModel -from pydantic.types import EmailStr app = FastAPI() -class UserIn(BaseModel): - username: str - password: str - email: EmailStr - full_name: str = None +class Item(BaseModel): + name: str + description: str = None + price: float + tax: float = None + tags: Set[str] = [] -# Don't do this in production! -@app.post("/user/", response_model=UserIn) -async def create_user(*, user: UserIn): - return user +@app.post("/items/", response_model=Item) +async def create_item(*, item: Item): + return item diff --git a/docs/tutorial/src/tutorial48.py b/docs/tutorial/src/tutorial48.py index c8ea361d8..3fb475b9d 100644 --- a/docs/tutorial/src/tutorial48.py +++ b/docs/tutorial/src/tutorial48.py @@ -12,12 +12,7 @@ class UserIn(BaseModel): full_name: str = None -class UserOut(BaseModel): - username: str - email: EmailStr - full_name: str = None - - -@app.post("/user/", response_model=UserOut) +# Don't do this in production! +@app.post("/user/", response_model=UserIn) async def create_user(*, user: UserIn): return user diff --git a/docs/tutorial/src/tutorial49.py b/docs/tutorial/src/tutorial49.py index aa8e7dad4..c8ea361d8 100644 --- a/docs/tutorial/src/tutorial49.py +++ b/docs/tutorial/src/tutorial49.py @@ -18,25 +18,6 @@ class UserOut(BaseModel): full_name: str = None -class UserInDB(BaseModel): - username: str - hashed_password: str - email: EmailStr - full_name: str = None - - -def fake_password_hasher(raw_password: str): - return "supersecret" + raw_password - - -def fake_save_user(user_in: UserIn): - hashed_password = fake_password_hasher(user_in.password) - user_in_db = UserInDB(**user_in.dict(), hashed_password=hashed_password) - print("User saved! ..not really") - return user_in_db - - @app.post("/user/", response_model=UserOut) -async def create_user(*, user_in: UserIn): - user_saved = fake_save_user(user_in) - return user_saved +async def create_user(*, user: UserIn): + return user diff --git a/docs/tutorial/src/tutorial50.py b/docs/tutorial/src/tutorial50.py index 605baf91f..aa8e7dad4 100644 --- a/docs/tutorial/src/tutorial50.py +++ b/docs/tutorial/src/tutorial50.py @@ -5,22 +5,24 @@ from pydantic.types import EmailStr app = FastAPI() -class UserBase(BaseModel): +class UserIn(BaseModel): username: str + password: str email: EmailStr full_name: str = None -class UserIn(UserBase): - password: str - - -class UserOut(UserBase): - pass +class UserOut(BaseModel): + username: str + email: EmailStr + full_name: str = None -class UserInDB(UserBase): +class UserInDB(BaseModel): + username: str hashed_password: str + email: EmailStr + full_name: str = None def fake_password_hasher(raw_password: str): diff --git a/docs/tutorial/src/tutorial51.py b/docs/tutorial/src/tutorial51.py index 0290b644d..605baf91f 100644 --- a/docs/tutorial/src/tutorial51.py +++ b/docs/tutorial/src/tutorial51.py @@ -1,8 +1,40 @@ -from fastapi import FastAPI, Form +from fastapi import FastAPI +from pydantic import BaseModel +from pydantic.types import EmailStr app = FastAPI() -@app.post("/login/") -async def login(*, username: str = Form(...), password: str = Form(...)): - return {"username": username} +class UserBase(BaseModel): + username: str + email: EmailStr + full_name: str = None + + +class UserIn(UserBase): + password: str + + +class UserOut(UserBase): + pass + + +class UserInDB(UserBase): + hashed_password: str + + +def fake_password_hasher(raw_password: str): + return "supersecret" + raw_password + + +def fake_save_user(user_in: UserIn): + hashed_password = fake_password_hasher(user_in.password) + user_in_db = UserInDB(**user_in.dict(), hashed_password=hashed_password) + print("User saved! ..not really") + return user_in_db + + +@app.post("/user/", response_model=UserOut) +async def create_user(*, user_in: UserIn): + user_saved = fake_save_user(user_in) + return user_saved diff --git a/docs/tutorial/src/tutorial52.py b/docs/tutorial/src/tutorial52.py index 3e99fcdde..0290b644d 100644 --- a/docs/tutorial/src/tutorial52.py +++ b/docs/tutorial/src/tutorial52.py @@ -1,8 +1,8 @@ -from fastapi import FastAPI, File +from fastapi import FastAPI, Form app = FastAPI() -@app.post("/files/") -async def create_file(*, file: bytes = File(...)): - return {"file_size": len(file)} +@app.post("/login/") +async def login(*, username: str = Form(...), password: str = Form(...)): + return {"username": username} diff --git a/docs/tutorial/src/tutorial53.py b/docs/tutorial/src/tutorial53.py index 1882a6397..3e99fcdde 100644 --- a/docs/tutorial/src/tutorial53.py +++ b/docs/tutorial/src/tutorial53.py @@ -1,8 +1,8 @@ -from fastapi import FastAPI, File, Form +from fastapi import FastAPI, File app = FastAPI() @app.post("/files/") -async def create_file(*, file: bytes = File(...), token: str = Form(...)): - return {"file_size": len(file), "token": token} +async def create_file(*, file: bytes = File(...)): + return {"file_size": len(file)} diff --git a/docs/tutorial/src/tutorial54.py b/docs/tutorial/src/tutorial54.py index b48601867..1882a6397 100644 --- a/docs/tutorial/src/tutorial54.py +++ b/docs/tutorial/src/tutorial54.py @@ -1,20 +1,8 @@ -from typing import Set - -from fastapi import FastAPI -from pydantic import BaseModel -from starlette.status import HTTP_201_CREATED +from fastapi import FastAPI, File, Form app = FastAPI() -class Item(BaseModel): - name: str - description: str = None - price: float - tax: float = None - tags: Set[str] = [] - - -@app.post("/items/", response_model=Item, status_code=HTTP_201_CREATED) -async def create_item(*, item: Item): - return item +@app.post("/files/") +async def create_file(*, file: bytes = File(...), token: str = Form(...)): + return {"file_size": len(file), "token": token} diff --git a/docs/tutorial/src/tutorial55.py b/docs/tutorial/src/tutorial55.py index ccd5437da..b48601867 100644 --- a/docs/tutorial/src/tutorial55.py +++ b/docs/tutorial/src/tutorial55.py @@ -2,6 +2,7 @@ from typing import Set from fastapi import FastAPI from pydantic import BaseModel +from starlette.status import HTTP_201_CREATED app = FastAPI() @@ -14,6 +15,6 @@ class Item(BaseModel): tags: Set[str] = [] -@app.post("/items/", response_model=Item, tags=["items"]) +@app.post("/items/", response_model=Item, status_code=HTTP_201_CREATED) async def create_item(*, item: Item): return item diff --git a/docs/tutorial/src/tutorial56.py b/docs/tutorial/src/tutorial56.py index 106607fd2..ccd5437da 100644 --- a/docs/tutorial/src/tutorial56.py +++ b/docs/tutorial/src/tutorial56.py @@ -14,11 +14,6 @@ class Item(BaseModel): tags: Set[str] = [] -@app.post( - "/items/", - response_model=Item, - summary="Create an item", - description="Create an item with all the information, name, description, price, tax and a set of unique tags", -) +@app.post("/items/", response_model=Item, tags=["items"]) async def create_item(*, item: Item): return item diff --git a/docs/tutorial/src/tutorial57.py b/docs/tutorial/src/tutorial57.py index a4151a8cd..106607fd2 100644 --- a/docs/tutorial/src/tutorial57.py +++ b/docs/tutorial/src/tutorial57.py @@ -14,15 +14,11 @@ class Item(BaseModel): tags: Set[str] = [] -@app.post("/items/", response_model=Item, summary="Create an item") +@app.post( + "/items/", + response_model=Item, + summary="Create an item", + description="Create an item with all the information, name, description, price, tax and a set of unique tags", +) async def create_item(*, item: Item): - """ - Create an item with all the information: - - * name: each item must have a name - * description: a long description - * price: required - * tax: if the item doesn't have tax, you can omit this - * tags: a set of unique tag strings for this item - """ return item diff --git a/docs/tutorial/src/tutorial58.py b/docs/tutorial/src/tutorial58.py index f710e6c66..a4151a8cd 100644 --- a/docs/tutorial/src/tutorial58.py +++ b/docs/tutorial/src/tutorial58.py @@ -14,12 +14,7 @@ class Item(BaseModel): tags: Set[str] = [] -@app.post( - "/items/", - response_model=Item, - summary="Create an item", - response_description="The created item", -) +@app.post("/items/", response_model=Item, summary="Create an item") async def create_item(*, item: Item): """ Create an item with all the information: diff --git a/docs/tutorial/src/tutorial59.py b/docs/tutorial/src/tutorial59.py index 11f3de6db..f710e6c66 100644 --- a/docs/tutorial/src/tutorial59.py +++ b/docs/tutorial/src/tutorial59.py @@ -1,8 +1,33 @@ +from typing import Set + from fastapi import FastAPI +from pydantic import BaseModel app = FastAPI() -@app.get("/items/", deprecated=True) -async def read_items(): - return [{"item_id": "Foo"}] +class Item(BaseModel): + name: str + description: str = None + price: float + tax: float = None + tags: Set[str] = [] + + +@app.post( + "/items/", + response_model=Item, + summary="Create an item", + response_description="The created item", +) +async def create_item(*, item: Item): + """ + Create an item with all the information: + + * name: each item must have a name + * description: a long description + * price: required + * tax: if the item doesn't have tax, you can omit this + * tags: a set of unique tag strings for this item + """ + return item diff --git a/docs/tutorial/src/tutorial60.py b/docs/tutorial/src/tutorial60.py index fafa8ffb8..11f3de6db 100644 --- a/docs/tutorial/src/tutorial60.py +++ b/docs/tutorial/src/tutorial60.py @@ -3,6 +3,6 @@ from fastapi import FastAPI app = FastAPI() -@app.get("/items/", operation_id="some_specific_id_you_define") +@app.get("/items/", deprecated=True) async def read_items(): return [{"item_id": "Foo"}] diff --git a/docs/tutorial/src/tutorial61.py b/docs/tutorial/src/tutorial61.py index dcc358e32..fafa8ffb8 100644 --- a/docs/tutorial/src/tutorial61.py +++ b/docs/tutorial/src/tutorial61.py @@ -3,6 +3,6 @@ from fastapi import FastAPI app = FastAPI() -@app.get("/items/", include_in_schema=False) +@app.get("/items/", operation_id="some_specific_id_you_define") async def read_items(): return [{"item_id": "Foo"}] diff --git a/docs/tutorial/src/tutorial62.py b/docs/tutorial/src/tutorial62.py index bba3f342d..dcc358e32 100644 --- a/docs/tutorial/src/tutorial62.py +++ b/docs/tutorial/src/tutorial62.py @@ -1,9 +1,8 @@ from fastapi import FastAPI -from starlette.responses import UJSONResponse app = FastAPI() -@app.get("/items/", content_type=UJSONResponse) +@app.get("/items/", include_in_schema=False) async def read_items(): return [{"item_id": "Foo"}] diff --git a/docs/tutorial/src/tutorial63.py b/docs/tutorial/src/tutorial63.py index 214e64263..bba3f342d 100644 --- a/docs/tutorial/src/tutorial63.py +++ b/docs/tutorial/src/tutorial63.py @@ -1,18 +1,9 @@ from fastapi import FastAPI -from starlette.responses import HTMLResponse +from starlette.responses import UJSONResponse app = FastAPI() -@app.get("/items/", content_type=HTMLResponse) +@app.get("/items/", content_type=UJSONResponse) async def read_items(): - return """ - - - Some HTML in here - - -

Look ma! HTML!

- - - """ + return [{"item_id": "Foo"}] diff --git a/docs/tutorial/src/tutorial64.py b/docs/tutorial/src/tutorial64.py index 82a51634e..214e64263 100644 --- a/docs/tutorial/src/tutorial64.py +++ b/docs/tutorial/src/tutorial64.py @@ -1,27 +1,18 @@ -from fastapi import Depends, FastAPI -from pydantic import BaseModel +from fastapi import FastAPI +from starlette.responses import HTMLResponse app = FastAPI() -fake_items_db = [{"item_name": "Foo"}, {"item_name": "Bar"}, {"item_name": "Baz"}] - - -class CommonQueryParams(BaseModel): - q: str = None - skip: int = None - limit: int = None - - -async def common_parameters(q: str = None, skip: int = 0, limit: int = 100): - return CommonQueryParams(q=q, skip=skip, limit=limit) - - -@app.get("/items/") -async def read_items(commons: CommonQueryParams = Depends(common_parameters)): - response = {} - if commons.q: - response.update({"q": commons.q}) - items = fake_items_db[commons.skip : commons.limit] - response.update({"items": items}) - return response +@app.get("/items/", content_type=HTMLResponse) +async def read_items(): + return """ + + + Some HTML in here + + +

Look ma! HTML!

+ + + """ diff --git a/docs/tutorial/src/tutorial65.py b/docs/tutorial/src/tutorial65.py index e015f9585..82a51634e 100644 --- a/docs/tutorial/src/tutorial65.py +++ b/docs/tutorial/src/tutorial65.py @@ -1,34 +1,27 @@ -from typing import List - -from fastapi import Cookie, Depends, FastAPI +from fastapi import Depends, FastAPI from pydantic import BaseModel app = FastAPI() -class InterestsTracker(BaseModel): - track_code: str - interests: List[str] +fake_items_db = [{"item_name": "Foo"}, {"item_name": "Bar"}, {"item_name": "Baz"}] -fake_tracked_users_db = { - "Foo": {"track_code": "Foo", "interests": ["sports", "movies"]}, - "Bar": {"track_code": "Bar", "interests": ["food", "shows"]}, - "Baz": {"track_code": "Baz", "interests": ["gaming", "virtual reality"]}, -} +class CommonQueryParams(BaseModel): + q: str = None + skip: int = None + limit: int = None -async def get_tracked_interests(track_code: str = Cookie(None)): - if track_code in fake_tracked_users_db: - track_dict = fake_tracked_users_db[track_code] - track = InterestsTracker(**track_dict) - return track - return None +async def common_parameters(q: str = None, skip: int = 0, limit: int = 100): + return CommonQueryParams(q=q, skip=skip, limit=limit) -@app.get("/interests/") -async def read_interests( - tracked_interests: InterestsTracker = Depends(get_tracked_interests) -): - response = {"interests": tracked_interests.interests} +@app.get("/items/") +async def read_items(commons: CommonQueryParams = Depends(common_parameters)): + response = {} + if commons.q: + response.update({"q": commons.q}) + items = fake_items_db[commons.skip : commons.limit] + response.update({"items": items}) return response diff --git a/docs/tutorial/src/tutorial66.py b/docs/tutorial/src/tutorial66.py index 3697b170a..e015f9585 100644 --- a/docs/tutorial/src/tutorial66.py +++ b/docs/tutorial/src/tutorial66.py @@ -1,4 +1,3 @@ -from random import choice from typing import List from fastapi import Cookie, Depends, FastAPI @@ -27,23 +26,9 @@ async def get_tracked_interests(track_code: str = Cookie(None)): return None -class ComplexTracker: - def __init__(self, tracker: InterestsTracker = Depends(get_tracked_interests)): - self.tracker = tracker - - def random_interest(self): - """ - Get a random interest from the tracked ones for the current user. - If the user doesn't have tracked interests, return a random one from the ones available. - """ - if self.tracker.interests: - return choice(self.tracker.interests) - return choice( - ["sports", "movies", "food", "shows", "gaming", "virtual reality"] - ) - - -@app.get("/suggested-category") -async def read_suggested_category(tracker: ComplexTracker = Depends(None)): - response = {"category": tracker.random_interest()} +@app.get("/interests/") +async def read_interests( + tracked_interests: InterestsTracker = Depends(get_tracked_interests) +): + response = {"interests": tracked_interests.interests} return response diff --git a/docs/tutorial/src/tutorial67.py b/docs/tutorial/src/tutorial67.py index 720604c02..3697b170a 100644 --- a/docs/tutorial/src/tutorial67.py +++ b/docs/tutorial/src/tutorial67.py @@ -1,52 +1,49 @@ -from fastapi import FastAPI +from random import choice +from typing import List -from sqlalchemy import Boolean, Column, Integer, String, create_engine -from sqlalchemy.ext.declarative import declarative_base, declared_attr -from sqlalchemy.orm import scoped_session, sessionmaker - -# SQLAlchemy specific code, as with any other app - - -SQLALCHEMY_DATABASE_URI = "postgresql://user:password@postgresserver/db" - -# By creating this a CustomBase class and inheriting from it, your models will have -# automatic __tablename__ attributes. So you don't have to declare them. -# So, your models will behave very similarly to, for example, Flask-SQLAlchemy - - -class CustomBase: - # Generate __tablename__ automatically - @declared_attr - def __tablename__(cls): - return cls.__name__.lower() +from fastapi import Cookie, Depends, FastAPI +from pydantic import BaseModel +app = FastAPI() -Base = declarative_base(cls=CustomBase) +class InterestsTracker(BaseModel): + track_code: str + interests: List[str] -class User(Base): - # Own properties - id = Column(Integer, primary_key=True, index=True) - email = Column(String, unique=True, index=True) - hashed_password = Column(String) - is_active = Column(Boolean(), default=True) +fake_tracked_users_db = { + "Foo": {"track_code": "Foo", "interests": ["sports", "movies"]}, + "Bar": {"track_code": "Bar", "interests": ["food", "shows"]}, + "Baz": {"track_code": "Baz", "interests": ["gaming", "virtual reality"]}, +} -engine = create_engine(SQLALCHEMY_DATABASE_URI, convert_unicode=True) -db_session = scoped_session( - sessionmaker(autocommit=False, autoflush=False, bind=engine) -) +async def get_tracked_interests(track_code: str = Cookie(None)): + if track_code in fake_tracked_users_db: + track_dict = fake_tracked_users_db[track_code] + track = InterestsTracker(**track_dict) + return track + return None -def get_user(username, db_session): - return db_session.query(User).filter(User.id == username).first() +class ComplexTracker: + def __init__(self, tracker: InterestsTracker = Depends(get_tracked_interests)): + self.tracker = tracker -# FastAPI specific code -app = FastAPI() + def random_interest(self): + """ + Get a random interest from the tracked ones for the current user. + If the user doesn't have tracked interests, return a random one from the ones available. + """ + if self.tracker.interests: + return choice(self.tracker.interests) + return choice( + ["sports", "movies", "food", "shows", "gaming", "virtual reality"] + ) -@app.get("/users/{username}") -def read_user(username: str): - user = get_user(username, db_session) - return user +@app.get("/suggested-category") +async def read_suggested_category(tracker: ComplexTracker = Depends(None)): + response = {"category": tracker.random_interest()} + return response diff --git a/docs/tutorial/src/tutorial68.py b/docs/tutorial/src/tutorial68.py index 26897e1c9..720604c02 100644 --- a/docs/tutorial/src/tutorial68.py +++ b/docs/tutorial/src/tutorial68.py @@ -1,49 +1,45 @@ -from typing import Optional - from fastapi import FastAPI -from pydantic import BaseModel -from app.models.config import USERPROFILE_DOC_TYPE -from couchbase import LOCKMODE_WAIT -from couchbase.bucket import Bucket -from couchbase.cluster import Cluster, PasswordAuthenticator +from sqlalchemy import Boolean, Column, Integer, String, create_engine +from sqlalchemy.ext.declarative import declarative_base, declared_attr +from sqlalchemy.orm import scoped_session, sessionmaker +# SQLAlchemy specific code, as with any other app -def get_bucket(): - cluster = Cluster("couchbase://couchbasehost:8091") - authenticator = PasswordAuthenticator("username", "password") - cluster.authenticate(authenticator) - bucket: Bucket = cluster.open_bucket("bucket_name", lockmode=LOCKMODE_WAIT) - return bucket +SQLALCHEMY_DATABASE_URI = "postgresql://user:password@postgresserver/db" -class User(BaseModel): - username: str - email: Optional[str] = None - full_name: Optional[str] = None - disabled: Optional[bool] = None +# By creating this a CustomBase class and inheriting from it, your models will have +# automatic __tablename__ attributes. So you don't have to declare them. +# So, your models will behave very similarly to, for example, Flask-SQLAlchemy -class UserInDB(User): - type: str = USERPROFILE_DOC_TYPE - hashed_password: str +class CustomBase: + # Generate __tablename__ automatically + @declared_attr + def __tablename__(cls): + return cls.__name__.lower() - class Meta: - key: Optional[str] = None +Base = declarative_base(cls=CustomBase) -def get_user_doc_id(username): - return f"userprofile::{username}" +class User(Base): + # Own properties + id = Column(Integer, primary_key=True, index=True) + email = Column(String, unique=True, index=True) + hashed_password = Column(String) + is_active = Column(Boolean(), default=True) -def get_user(bucket: Bucket, username: str): - doc_id = get_user_doc_id(username) - result = bucket.get(doc_id, quiet=True) - if not result.value: - return None - user = UserInDB(**result.value) - user.Meta.key = result.key - return user + +engine = create_engine(SQLALCHEMY_DATABASE_URI, convert_unicode=True) +db_session = scoped_session( + sessionmaker(autocommit=False, autoflush=False, bind=engine) +) + + +def get_user(username, db_session): + return db_session.query(User).filter(User.id == username).first() # FastAPI specific code @@ -52,6 +48,5 @@ app = FastAPI() @app.get("/users/{username}") def read_user(username: str): - bucket = get_bucket() - user = get_user(bucket=bucket, username=username) + user = get_user(username, db_session) return user