Skip to content

Commit 314a25f

Browse files
committed
update docs string
1 parent 327e1f7 commit 314a25f

File tree

3 files changed

+147
-37
lines changed

3 files changed

+147
-37
lines changed

README.md

Lines changed: 58 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -29,6 +29,7 @@
2929
- [Path Parameter](#path-parameter)
3030
- [Query Parameter](#query-parameter)
3131
- [Request Body](#request-body)
32+
- [Foreign Tree](#foreign-tree)
3233
- [Upsert](#upsert)
3334
- [Add description into docs](#add-description-into-docs)
3435
- [Relationship](#relationship)
@@ -43,9 +44,9 @@ I believe that many people who work with FastApi to build RESTful CRUD services
4344
`FastAPI Quick CRUD` can generate CRUD methods in FastApi from an SQLAlchemy schema:
4445

4546
- Get one
46-
- Get one with foreign key (IN DEVELOPMENT)
47+
- Get one with foreign key
4748
- Get many
48-
- Get many with foreign key (IN DEVELOPMENT)
49+
- Get many with foreign key
4950
- Update one
5051
- Update many
5152
- Patch one
@@ -156,6 +157,55 @@ app.include_router(crud_route_1)
156157
app.include_router(crud_route_2)
157158
```
158159

160+
### Foreign Tree With Relationship
161+
```python
162+
163+
class Account(Base):
164+
__tablename__ = "account"
165+
id = Column(Integer, primary_key=True, autoincrement=True)
166+
blog_post = relationship("BlogPost", back_populates="account")
167+
168+
169+
class BlogPost(Base):
170+
__tablename__ = "blog_post"
171+
id = Column(Integer, primary_key=True, autoincrement=True)
172+
account_id = Column(Integer, ForeignKey("account.id"), nullable=False)
173+
account = relationship("Account", back_populates="blog_post")
174+
blog_comment = relationship("BlogComment", back_populates="blog_post")
175+
176+
177+
class BlogComment(Base):
178+
__tablename__ = "blog_comment"
179+
id = Column(Integer, primary_key=True, autoincrement=True)
180+
blog_id = Column(Integer, ForeignKey("blog_post.id"), nullable=False)
181+
blog_post = relationship("BlogPost", back_populates="blog_comment")
182+
183+
184+
crud_route_parent = crud_router_builder(
185+
db_model=Account,
186+
prefix="/account",
187+
tags=["account"],
188+
foreign_include=[BlogComment, BlogPost]
189+
190+
)
191+
crud_route_child1 = generic_sql_crud_router_builder(
192+
db_model=BlogPost,
193+
prefix="/blog_post",
194+
tags=["blog_post"],
195+
foreign_include=[BlogComment]
196+
197+
)
198+
crud_route_child2 = generic_sql_crud_router_builder(
199+
db_model=BlogComment,
200+
prefix="/blog_comment",
201+
tags=["blog_comment"]
202+
203+
)
204+
205+
app = FastAPI()
206+
[app.include_router(i) for i in [crud_route_parent, crud_route_child1, crud_route_child2]]
207+
208+
```
159209

160210
### SQLAlchemy to Pydantic Model Converter And Build your own API([example](https://github.com/LuisLuii/FastAPIQuickCRUD/blob/main/tutorial/basic_usage/quick_usage_with_async_SQLALchemy_Base.py))
161211
```python
@@ -436,6 +486,12 @@ In the basic request body in the api generated by this tool, some fields are opt
436486
* [x] it is not a primary key, but the `server_default` or `default` is True
437487
* [x] The field is nullable
438488

489+
490+
### Foreign Tree
491+
TBC
492+
493+
494+
439495
## Upsert
440496

441497
** Upsert supports PosgreSQL only yet

src/fastapi_quickcrud/crud_router.py

Lines changed: 33 additions & 35 deletions
Original file line numberDiff line numberDiff line change
@@ -22,7 +22,7 @@
2222
from .misc.crud_model import CRUDModel
2323
from .misc.memory_sql import async_memory_db, sync_memory_db
2424
from .misc.type import CrudMethods, SqlType
25-
from .misc.utils import convert_table_to_model
25+
from .misc.utils import convert_table_to_model, Base
2626

2727
CRUDModelType = TypeVar("CRUDModelType", bound=BaseModel)
2828
CompulsoryQueryModelType = TypeVar("CompulsoryQueryModelType", bound=BaseModel)
@@ -39,34 +39,20 @@ def crud_router_builder(
3939
dependencies: Optional[List[callable]] = None,
4040
crud_models: Optional[CRUDModel] = None,
4141
async_mode: Optional[bool] = None,
42-
foreign_include: Optional[any] = None,
42+
foreign_include: Optional[Base] = None,
4343
sql_type: Optional[SqlType] = None,
4444
**router_kwargs: Any) -> APIRouter:
4545
"""
46-
:param db_session: Callable function
47-
db_session should be a callable function, and return a session generator.
48-
Also you can handle commit by yourelf or othe business logic
49-
50-
SQLAlchemy based example(SQLAlchemy was supported async since 1.4 version):
51-
async:
52-
async def get_transaction_session() -> AsyncSession:
53-
async with async_session() as session:
54-
async with session.begin():
55-
yield session
56-
sync:
57-
def get_transaction_session():
58-
try:
59-
db = sync_session()
60-
yield db
61-
db.commit()
62-
except Exception as e:
63-
db.rollback()
64-
raise e
65-
finally:
66-
db.close()
67-
68-
69-
:param crud_methods: List[CrudMethods]
46+
@param db_model:
47+
The Sqlalchemy Base model/Table you want to use it to build api.
48+
49+
@param db_session:
50+
The callable variable and return a session generator that will be used to get database connection session for fastapi.
51+
52+
@param autocommit:
53+
set False if you handle commit in your db_session.
54+
55+
@param crud_methods:
7056
Fastapi Quick CRUD supports a few of crud methods, and they save into the Enum class,
7157
get it by : from fastapi_quickcrud import CrudMethods
7258
example:
@@ -76,21 +62,33 @@ def get_transaction_session():
7662
specific resource, such as GET_ONE, UPDATE_ONE, DELETE_ONE, PATCH_ONE AND POST_REDIRECT_GET
7763
this is because POST_REDIRECT_GET need to redirect to GET_ONE api
7864
79-
:param exclude_columns: List[str]
65+
@param exclude_columns:
8066
Fastapi Quick CRUD will get all the columns in you table to generate a CRUD router,
8167
it is allow you exclude some columns you dont want it expose to operated by API
8268
note:
8369
if the column in exclude list but is it not nullable or no default_value, it may throw error
8470
when you do insert
8571
86-
:param crud_models:
87-
:param db_model:
88-
SQLAlchemy model,
89-
:param dependencies:
90-
:param async_mode:
91-
:param autocommit:
92-
:param router_kwargs: Optional arguments that ``APIRouter().include_router`` takes.
93-
:return:
72+
@param dependencies:
73+
A variable that will be added to the path operation decorators.
74+
75+
@param crud_models:
76+
You can use the sqlalchemy_to_pydantic() to build your own Pydantic model CRUD set
77+
78+
@param async_mode:
79+
As your database connection
80+
81+
@param foreign_include: BaseModel
82+
Used to build foreign tree api
83+
84+
@param sql_type:
85+
You sql database type
86+
87+
@param router_kwargs:
88+
other argument for FastApi's views
89+
90+
@return:
91+
APIRouter for fastapi
9492
"""
9593

9694
db_model, NO_PRIMARY_KEY = convert_table_to_model(db_model)

tutorial/foreign_tree/sample_tree.py

Lines changed: 56 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,56 @@
1+
from fastapi import FastAPI
2+
import uvicorn
3+
from fastapi_quickcrud import crud_router_builder
4+
from sqlalchemy import *
5+
from sqlalchemy.orm import *
6+
from fastapi_quickcrud.crud_router import generic_sql_crud_router_builder
7+
8+
Base = declarative_base()
9+
10+
11+
class Account(Base):
12+
__tablename__ = "account"
13+
id = Column(Integer, primary_key=True, autoincrement=True)
14+
blog_post = relationship("BlogPost", back_populates="account")
15+
16+
17+
class BlogPost(Base):
18+
__tablename__ = "blog_post"
19+
id = Column(Integer, primary_key=True, autoincrement=True)
20+
account_id = Column(Integer, ForeignKey("account.id"), nullable=False)
21+
account = relationship("Account", back_populates="blog_post")
22+
blog_comment = relationship("BlogComment", back_populates="blog_post")
23+
24+
25+
class BlogComment(Base):
26+
__tablename__ = "blog_comment"
27+
id = Column(Integer, primary_key=True, autoincrement=True)
28+
blog_id = Column(Integer, ForeignKey("blog_post.id"), nullable=False)
29+
blog_post = relationship("BlogPost", back_populates="blog_comment")
30+
31+
32+
crud_route_parent = crud_router_builder(
33+
db_model=Account,
34+
prefix="/account",
35+
tags=["account"],
36+
foreign_include=[BlogComment, BlogPost]
37+
38+
)
39+
crud_route_child1 = generic_sql_crud_router_builder(
40+
db_model=BlogPost,
41+
prefix="/blog_post",
42+
tags=["blog_post"],
43+
foreign_include=[BlogComment]
44+
45+
)
46+
crud_route_child2 = generic_sql_crud_router_builder(
47+
db_model=BlogComment,
48+
prefix="/blog_comment",
49+
tags=["blog_comment"]
50+
51+
)
52+
53+
app = FastAPI()
54+
[app.include_router(i) for i in [crud_route_parent, crud_route_child1, crud_route_child2]]
55+
56+
uvicorn.run(app, host="0.0.0.0", port=8002, debug=False)

0 commit comments

Comments
 (0)