1010 Depends , APIRouter
1111from pydantic import \
1212 BaseModel
13- from sqlalchemy .orm import declarative_base
1413from sqlalchemy .sql .schema import Table
1514
1615from . import sqlalchemy_to_pydantic
2322from .misc .crud_model import CRUDModel
2423from .misc .memory_sql import async_memory_db , sync_memory_db
2524from .misc .type import CrudMethods , SqlType
26- from .misc .utils import convert_table_to_model
25+ from .misc .utils import convert_table_to_model , Base
2726
2827CRUDModelType = TypeVar ("CRUDModelType" , bound = BaseModel )
2928CompulsoryQueryModelType = TypeVar ("CompulsoryQueryModelType" , bound = BaseModel )
@@ -40,33 +39,20 @@ def crud_router_builder(
4039 dependencies : Optional [List [callable ]] = None ,
4140 crud_models : Optional [CRUDModel ] = None ,
4241 async_mode : Optional [bool ] = 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 )
@@ -108,18 +106,19 @@ def get_transaction_session():
108106
109107 if async_mode is None :
110108 async_mode = inspect .isasyncgen (db_session ())
111-
109+
112110 if sql_type is None :
113111 async def async_runner (f ):
114112 return [i .bind .name async for i in f ()]
113+
115114 try :
116115 if async_mode :
117116 sql_type , = asyncio .get_event_loop ().run_until_complete (async_runner (db_session ))
118117 else :
119118 sql_type , = [i .bind .name for i in db_session ()]
120119 except Exception :
121120 raise RuntimeError ("Some unknown problem occurred error, maybe you are uvicorn.run with reload=True. "
122- "Try declaring sql_type for crud_router_builder yourself using from fastapi_quickcrud.misc.type import SqlType" )
121+ "Try declaring sql_type for crud_router_builder yourself using from fastapi_quickcrud.misc.type import SqlType" )
123122
124123 if not crud_methods and NO_PRIMARY_KEY == False :
125124 crud_methods = CrudMethods .get_declarative_model_full_crud_method ()
@@ -144,9 +143,15 @@ async def async_runner(f):
144143 crud_methods = crud_methods ,
145144 exclude_columns = exclude_columns ,
146145 sql_type = sql_type ,
146+ foreign_include = foreign_include ,
147147 exclude_primary_key = NO_PRIMARY_KEY )
148148
149- crud_service = query_service (model = db_model , async_mode = async_mode )
149+ foreign_table_mapping = {db_model .__tablename__ : db_model }
150+ if foreign_include :
151+ for i in foreign_include :
152+ model , _ = convert_table_to_model (i )
153+ foreign_table_mapping [model .__tablename__ ] = i
154+ crud_service = query_service (model = db_model , async_mode = async_mode , foreign_table_mapping = foreign_table_mapping )
150155 # else:
151156 # crud_service = SQLAlchemyPostgreQueryService(model=db_model, async_mode=async_mode)
152157
@@ -372,6 +377,48 @@ def put_many_api(request_response_model: dict, dependencies):
372377 async_mode = async_mode ,
373378 response_model = _response_model )
374379
380+ def find_one_foreign_tree_api (request_response_model : dict , dependencies ):
381+ _foreign_list_model = request_response_model .get ('foreignListModel' , None )
382+ for i in _foreign_list_model :
383+ _request_query_model = i ["request_query_model" ]
384+ _response_model = i ["response_model" ]
385+ _path = i ["path" ]
386+ _function_name = i ["function_name" ]
387+ request_url_param_model = i ["primary_key_dataclass_model" ]
388+ routes_source .find_one_foreign_tree (path = _path ,
389+ request_query_model = _request_query_model ,
390+ response_model = _response_model ,
391+ request_url_param_model = request_url_param_model ,
392+ db_session = db_session ,
393+ query_service = crud_service ,
394+ parsing_service = result_parser ,
395+ execute_service = execute_service ,
396+ dependencies = dependencies ,
397+ api = api ,
398+ function_name = _function_name ,
399+ async_mode = async_mode )
400+
401+ def find_many_foreign_tree_api (request_response_model : dict , dependencies ):
402+ _foreign_list_model = request_response_model .get ('foreignListModel' , None )
403+ for i in _foreign_list_model :
404+ _request_query_model = i ["request_query_model" ]
405+ _response_model = i ["response_model" ]
406+ _path = i ["path" ]
407+ _function_name = i ["function_name" ]
408+ request_url_param_model = i ["primary_key_dataclass_model" ]
409+ routes_source .find_many_foreign_tree (path = _path ,
410+ request_query_model = _request_query_model ,
411+ response_model = _response_model ,
412+ request_url_param_model = request_url_param_model ,
413+ db_session = db_session ,
414+ query_service = crud_service ,
415+ parsing_service = result_parser ,
416+ execute_service = execute_service ,
417+ dependencies = dependencies ,
418+ api = api ,
419+ async_mode = async_mode ,
420+ function_name = _function_name )
421+
375422 api_register = {
376423 CrudMethods .FIND_ONE .value : find_one_api ,
377424 CrudMethods .FIND_MANY .value : find_many_api ,
@@ -385,7 +432,9 @@ def put_many_api(request_response_model: dict, dependencies):
385432 CrudMethods .PATCH_ONE .value : patch_one_api ,
386433 CrudMethods .PATCH_MANY .value : patch_many_api ,
387434 CrudMethods .UPDATE_ONE .value : put_one_api ,
388- CrudMethods .UPDATE_MANY .value : put_many_api
435+ CrudMethods .UPDATE_MANY .value : put_many_api ,
436+ CrudMethods .FIND_ONE_WITH_FOREIGN_TREE .value : find_one_foreign_tree_api ,
437+ CrudMethods .FIND_MANY_WITH_FOREIGN_TREE .value : find_many_foreign_tree_api
389438 }
390439 api = APIRouter (** router_kwargs )
391440
0 commit comments