Skip to content

Commit 6289607

Browse files
CosmoVmahenzon
authored andcommitted
updated client generated id example
1 parent 3c6a097 commit 6289607

2 files changed

Lines changed: 145 additions & 12 deletions

File tree

docs/client_generated_id.rst

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -22,7 +22,8 @@ Response:
2222

2323
In order to do this you need to define an ``id`` with the Field keyword **client_can_set_id** in the
2424
``schema`` or ``schema_in_post``.
25-
Schematically it looks like this:
25+
26+
Example:
2627

2728
.. literalinclude:: ./python_snippets/client_generated_id/schematic_example.py
2829
:language: python
Lines changed: 143 additions & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -1,22 +1,154 @@
1-
from fastapi import FastAPI
2-
from pydantic import BaseModel, Field
1+
import sys
2+
from pathlib import Path
3+
4+
import uvicorn
5+
from fastapi import APIRouter, Depends, FastAPI
6+
from pydantic import Field, BaseModel as PydanticBaseModel
7+
from sqlalchemy import Column, Integer, Text
8+
from sqlalchemy.engine import make_url
9+
from sqlalchemy.ext.asyncio import AsyncSession, create_async_engine
10+
from sqlalchemy.ext.declarative import declarative_base
11+
from sqlalchemy.orm import sessionmaker
312

413
from fastapi_jsonapi import RoutersJSONAPI
14+
from fastapi_jsonapi.misc.sqla.generics.base import DetailViewBaseGeneric, ListViewBaseGeneric
15+
from fastapi_jsonapi.views.utils import HTTPMethod, HTTPMethodConfig
16+
from fastapi_jsonapi.views.view_base import ViewBase
17+
18+
CURRENT_FILE = Path(__file__).resolve()
19+
CURRENT_DIR = CURRENT_FILE.parent
20+
PROJECT_DIR = CURRENT_DIR.parent.parent
21+
DB_URL = f"sqlite+aiosqlite:///{CURRENT_DIR.absolute()}/db.sqlite3"
22+
sys.path.append(str(PROJECT_DIR))
23+
24+
Base = declarative_base()
25+
526

27+
class User(Base):
28+
__tablename__ = "users"
29+
id = Column(Integer, primary_key=True, autoincrement=False)
30+
name: str = Column(Text, nullable=True)
631

7-
class PersonAttributesSchema(BaseModel):
32+
33+
class BaseModel(PydanticBaseModel):
34+
class Config:
35+
orm_mode = True
36+
37+
38+
class UserAttributesBaseSchema(BaseModel):
839
name: str
940

1041

11-
class PersonSchemaIn(BaseModel):
42+
class UserSchema(UserAttributesBaseSchema):
43+
"""User base schema."""
44+
45+
46+
class UserPatchSchema(UserAttributesBaseSchema):
47+
"""User PATCH schema."""
48+
49+
50+
class UserInSchema(UserAttributesBaseSchema):
51+
"""User input schema."""
52+
1253
id: int = Field(client_can_set_id=True)
1354

1455

15-
app = FastAPI()
56+
async def get_session():
57+
sess = sessionmaker(
58+
bind=create_async_engine(url=make_url(DB_URL)),
59+
class_=AsyncSession,
60+
expire_on_commit=False,
61+
)
62+
async with sess() as db_session: # type: AsyncSession
63+
yield db_session
64+
await db_session.rollback()
65+
66+
67+
async def sqlalchemy_init() -> None:
68+
engine = create_async_engine(url=make_url(DB_URL))
69+
async with engine.begin() as conn:
70+
await conn.run_sync(Base.metadata.create_all)
71+
72+
73+
class SessionDependency(BaseModel):
74+
session: AsyncSession = Depends(get_session)
75+
76+
class Config:
77+
arbitrary_types_allowed = True
78+
79+
80+
def session_dependency_handler(view: ViewBase, dto: BaseModel) -> dict:
81+
return {"session": dto.session}
82+
83+
84+
class UserDetailView(DetailViewBaseGeneric):
85+
method_dependencies = {
86+
HTTPMethod.ALL: HTTPMethodConfig(
87+
dependencies=SessionDependency,
88+
prepare_data_layer_kwargs=session_dependency_handler,
89+
)
90+
}
91+
92+
93+
class UserListView(ListViewBaseGeneric):
94+
method_dependencies = {
95+
HTTPMethod.ALL: HTTPMethodConfig(
96+
dependencies=SessionDependency,
97+
prepare_data_layer_kwargs=session_dependency_handler,
98+
)
99+
}
100+
101+
102+
def add_routes(app: FastAPI):
103+
tags = [
104+
{
105+
"name": "User",
106+
"description": "",
107+
},
108+
]
109+
110+
routers: APIRouter = APIRouter()
111+
RoutersJSONAPI(
112+
router=routers,
113+
path="/user",
114+
tags=["User"],
115+
class_detail=UserDetailView,
116+
class_list=UserListView,
117+
schema=UserSchema,
118+
resource_type="user",
119+
schema_in_patch=UserPatchSchema,
120+
schema_in_post=UserInSchema,
121+
model=User,
122+
)
123+
124+
app.include_router(routers, prefix="")
125+
return tags
126+
127+
128+
def create_app() -> FastAPI:
129+
"""
130+
Create app factory.
131+
132+
:return: app
133+
"""
134+
app = FastAPI(
135+
title="FastAPI and SQLAlchemy",
136+
debug=True,
137+
openapi_url="/openapi.json",
138+
docs_url="/docs",
139+
)
140+
add_routes(app)
141+
app.on_event("startup")(sqlalchemy_init)
142+
return app
143+
144+
145+
app = create_app()
16146

17-
RoutersJSONAPI(
18-
app,
19-
# ...
20-
schema_in_post=PersonSchemaIn,
21-
# ...
22-
)
147+
if __name__ == "__main__":
148+
uvicorn.run(
149+
"test:app",
150+
host="0.0.0.0",
151+
port=8084,
152+
reload=True,
153+
app_dir=str(CURRENT_DIR),
154+
)

0 commit comments

Comments
 (0)