1515 SmallInteger ,
1616 delete ,
1717 func ,
18+ inspect ,
1819 select ,
1920)
20- from sqlalchemy .orm import Session
21+ from sqlalchemy .orm import MANYTOMANY , RelationshipProperty , Session
2122from starlette .requests import Request
2223from starlette .responses import RedirectResponse
2324
25+ from fast_tmp .responses import BaseRes , key_error , not_found_instance , single_pk
2426from fast_tmp .site import ModelAdmin , get_model_site
2527
2628from ..db import get_db_session
2729from ..models import User
2830from ..site .utils import clean_data_to_model , get_pk
2931from .depends import decode_access_token_from_data
30- from .responses import BaseRes , key_error , not_found_instance
3132
3233router = APIRouter ()
3334
@@ -85,13 +86,13 @@ def update_data(
8586 if not user :
8687 return RedirectResponse (request .url_for ("admin:login" ))
8788 data = clean_data_to_model (page_model .get_clean_fields (page_model .update_fields ), data )
88- w = get_pks (page_model , request )
89+ w = get_pks (page_model . model , request )
8990 if isinstance (w , BaseRes ):
9091 return w
9192 old_data = session .execute (select (page_model .model ).where (* w )).scalar_one_or_none ()
9293 if not old_data :
9394 return not_found_instance
94- page_model .update_model (old_data , data )
95+ page_model .update_model (old_data , data , session )
9596 session .commit ()
9697 return BaseRes ()
9798
@@ -106,13 +107,29 @@ def update_view(
106107 if not user :
107108 return RedirectResponse (request .url_for ("admin:login" ))
108109
109- pks = get_pks (page_model , request )
110+ pks = get_pks (page_model . model , request )
110111 if isinstance (pks , BaseRes ):
111112 return pks
112- data = session .execute (page_model .get_one_sql ( pks )).fetchone ()
113+ data = session .execute (select ( page_model .model ). where ( * pks )).scalar_one_or_none ()
113114 if not data :
114115 return not_found_instance
115- return BaseRes (data = dict (data ))
116+ res = {}
117+ for i in page_model .update_fields :
118+ if isinstance (i .property , RelationshipProperty ):
119+ prop = i .property
120+ if prop .direction in (MANYTOMANY ,): # TODO need onetomany
121+ pk = list (get_pk (prop .entity .class_ ).keys ())[0 ] # 只支持单主键
122+ # subs: str = getattr(data, i.key, "") # type: ignore
123+ # if not subs:
124+ # raise not_found_model
125+ # else:
126+ # # for sub in subs:
127+ # # pk_v=getattr(sub,pk)
128+ res [i .key ] = [getattr (sub , pk ) for sub in getattr (data , i .key )] # type: ignore
129+ else :
130+ res [i .key ] = getattr (data , i .key ) # type: ignore
131+
132+ return BaseRes (data = res )
116133
117134
118135@router .post ("/{resource}/create" )
@@ -127,7 +144,7 @@ def create(
127144 return RedirectResponse (request .url_for ("admin:login" ))
128145
129146 data = clean_data_to_model (page_model .create_fields , data )
130- instance = page_model .create_model (data )
147+ instance = page_model .create_model (data , session )
131148 session .add (instance )
132149 session .commit ()
133150 return BaseRes (data = data )
@@ -143,20 +160,31 @@ def delete_one(
143160 if not user :
144161 return RedirectResponse (request .url_for ("admin:login" ))
145162
146- w = get_pks (page_model , request )
163+ w = get_pks (page_model . model , request )
147164 if isinstance (w , BaseRes ):
148165 return w
149166 session .execute (delete (page_model .model ).where (* w ))
150167 session .commit ()
151168 return BaseRes ()
152169
153170
154- def get_pks (page_model : ModelAdmin , request : Request ):
171+ def clean_param (field_type , param : str ):
172+ if isinstance (
173+ field_type , (Integer , DECIMAL , BigInteger , Float , INTEGER , Numeric , SmallInteger )
174+ ):
175+ return int (param )
176+ elif isinstance (field_type , DateTime ):
177+ return datetime .strptime (param , "%Y-%m-%dT%H:%M:%S" )
178+ else :
179+ return param
180+
181+
182+ def get_pks (model , request : Request ):
155183 """
156184 获取要查询的单个instance的主键
157185 """
158186 params = dict (request .query_params )
159- pks = get_pk (page_model . model )
187+ pks = get_pk (model )
160188 w = []
161189 for k , v in params .items ():
162190 if pks .get (k ) is not None :
@@ -210,9 +238,62 @@ def get_selects(
210238 perPage : int = 10 ,
211239 page : int = 1 ,
212240):
241+ mapper = inspect (page_model .model )
242+ items = []
243+ total = 0
244+ for attr in mapper .attrs :
245+ if attr .key == field :
246+ relation_model = attr .entity .class_
247+ secondary = attr .secondary
248+ for col in secondary .foreign_key_constraints :
249+ if col .referred_table in mapper .tables :
250+ params = dict (request .query_params )
251+ if len (params ) > 1 :
252+ raise single_pk
253+ col_name = col .column_keys [0 ]
254+ for c in secondary .c :
255+ if c .key == col_name :
256+ clean_value = clean_param (c .type , list (params .values ())[0 ])
257+ sql = (
258+ select (* list (get_pk (relation_model ).values ()))
259+ .join (secondary )
260+ .where (c == clean_value )
261+ .limit (perPage )
262+ .offset ((page - 1 ) * perPage )
263+ )
264+ datas = session .execute (sql )
265+ total_f = session .execute (
266+ select (func .count ())
267+ .select_from (relation_model )
268+ .join (secondary )
269+ .where (col == list (params .values ())[0 ])
270+ ).fetchone ()
271+ if total_f is not None :
272+ total = total_f [0 ]
273+ for data in datas :
274+ items .append (dict (data ))
275+ return BaseRes (data = {"total" : total , "rows" : items })
276+
277+
278+ @router .get ("/{resource}/picks/{field}" )
279+ def get_picks (
280+ request : Request ,
281+ field : str = Path (...), # type: ignore
282+ page_model : ModelAdmin = Depends (get_model_site ),
283+ user : Optional [User ] = Depends (decode_access_token_from_data ),
284+ session : Session = Depends (get_db_session ),
285+ perPage : int = 10 ,
286+ page : int = 1 ,
287+ ):
288+ """
289+ 枚举选择
290+ """
213291 source_field = getattr (page_model .model , field )
214- relation_model = source_field .property .mapper .class_
292+ if isinstance (source_field .property , RelationshipProperty ):
293+ relation_model = source_field .property .mapper .class_
215294
295+ else :
296+ relation_model = source_field .property .mapper .class_
216297 datas = session .execute (
217298 select (list (get_pk (relation_model ).values ())).limit (perPage ).offset ((page - 1 ) * perPage )
218299 )
0 commit comments