1212from ..amis .actions import AjaxAction , DialogAction , DrawerAction
1313from ..amis .buttons import Operation
1414from ..amis .enums import ButtonLevelEnum
15+ from ..amis .filter import Filter , FilterModel
1516from ..amis .forms import Form
1617from ..amis .frame import Dialog , Drawer
18+ from .base import ModelFilter
1719from .util import AbstractControl , BaseAdminControl , RelationSelectApi , create_column
1820
1921logger = logging .getLogger (__file__ )
@@ -55,8 +57,8 @@ class ModelAdmin(DbSession): # todo inline字段必须都在update_fields内
5557 inline : Tuple [str , ...] = ()
5658 prefix : str
5759 # search list
58- search_fields : Tuple [str , ...] = ()
59- filter_fields : Tuple [str , ...] = ()
60+ searchs : Tuple [str , ...] = ()
61+ filters : Tuple [ModelFilter , ...] = ()
6062 # create
6163 create_fields : Tuple [str , ...] = ()
6264 # exclude: Tuple[Union[str, BaseModel], ...] = ()
@@ -77,12 +79,29 @@ class ModelAdmin(DbSession): # todo inline字段必须都在update_fields内
7779 list_per_page : int = 10 # 每页多少数据
7880 list_max_show_all : int = 200 # 最多每页多少数据
7981 selct_defs = None
82+ _filters = None
8083
8184 def name (self ) -> str :
8285 if self .__name is None :
8386 self .__name = self .model .__name__
8487 return self .__name
8588
89+ def get_filters (self ):
90+ if not self ._filters :
91+ self ._filters = {i .name : i for i in self .filters }
92+ return self ._filters
93+
94+ def queryset_filter (self , request : Request , queryset : QuerySet ):
95+ query = request .query_params
96+ filter_fs = self .get_filters ()
97+ for k , v in query .items ():
98+ if k in ("pk" , "page" , "perPage" ):
99+ continue
100+ func = filter_fs .get (k )
101+ if func is not None :
102+ queryset = func .queryset (request , queryset , v )
103+ return queryset
104+
86105 def get_create_fields (self ) -> Dict [str , BaseAdminControl ]:
87106 return {i : self .fields [i ] for i in self .create_fields }
88107
@@ -94,7 +113,7 @@ def get_update_fields_with_pk(self) -> Dict[str, BaseAdminControl]:
94113 ret ["pk" ] = self .fields ["pk" ]
95114 return ret
96115
97- async def get_create_dialogation_button (self , request : Request ):
116+ def get_create_dialogation_button (self , request : Request ):
98117 controls = self .get_create_fields ()
99118
100119 return DialogAction (
@@ -110,7 +129,7 @@ async def get_create_dialogation_button(self, request: Request):
110129 ),
111130 )
112131
113- async def get_list_page (self , request : Request ):
132+ def get_list_page (self , request : Request ):
114133 res = []
115134 for field_name , col in self .get_list_distplay ().items ():
116135 if field_name in self .inline :
@@ -128,7 +147,7 @@ def get_del_one_button(self):
128147 api = "delete:" + self .name () + "/delete/$pk" ,
129148 )
130149
131- async def get_update_one_button (self , request : Request ):
150+ def get_update_one_button (self , request : Request ):
132151 body = [i .get_control (request ) for i in self .get_update_fields ().values ()]
133152 return DialogAction (
134153 label = "修改" ,
@@ -145,30 +164,48 @@ async def get_update_one_button(self, request: Request):
145164 ),
146165 )
147166
148- async def get_operation (self , request : Request ):
167+ def get_operation (self , request : Request ):
149168 buttons = []
150169 if "put" in self .methods and self .update_fields :
151- buttons .append (await self .get_update_one_button (request ))
170+ buttons .append (self .get_update_one_button (request ))
152171 if "delete" in self .methods :
153172 buttons .append (self .get_del_one_button ())
154173 return Operation (buttons = buttons )
155174
156- async def get_crud (self , request : Request ):
175+ def get_filter_page (self , request : Request ):
176+ """
177+ 页面上的过滤框
178+ """
179+ return FilterModel (
180+ body = [
181+ Filter (
182+ type = v .type ,
183+ name = v .name ,
184+ label = v .label ,
185+ clearable = v .clearable ,
186+ placeholder = v .placeholder ,
187+ )
188+ for v in self .get_filters ().values ()
189+ ]
190+ )
191+
192+ def get_crud (self , request : Request ):
157193 body = []
158194 columns = []
159195 if "create" in self .methods and self .create_fields :
160- body .append (await self .get_create_dialogation_button (request ))
196+ body .append (self .get_create_dialogation_button (request ))
161197 if "list" in self .methods and self .list_display :
162- columns .extend (await self .get_list_page (request ))
163- columns .append (await self .get_operation (request ))
164- body .append (
165- CRUD (
166- api = self .prefix + "/list" ,
167- columns = columns ,
168- quickSaveItemApi = self .prefix + "/patch/" + "$pk" ,
169- syncLocation = False ,
170- )
198+ columns .extend (self .get_list_page (request ))
199+ columns .append (self .get_operation (request ))
200+ crud = CRUD (
201+ api = self .prefix + "/list" ,
202+ columns = columns ,
203+ quickSaveItemApi = self .prefix + "/patch/" + "$pk" ,
204+ syncLocation = False ,
171205 )
206+ if len (self .get_filters ()) > 0 :
207+ crud .filter = self .get_filter_page (request )
208+ body .append (crud )
172209 return body
173210
174211 def get_list_distplay (self ) -> Dict [str , BaseAdminControl ]:
@@ -182,8 +219,8 @@ def get_list_display_with_pk(self) -> Dict[str, BaseAdminControl]:
182219 ret ["pk" ] = self .fields ["pk" ]
183220 return ret
184221
185- async def get_app_page (self , request : Request ):
186- return Page (title = self .name (), body = await self .get_crud (request )).dict (exclude_none = True )
222+ def get_app_page (self , request : Request ):
223+ return Page (title = self .name (), body = self .get_crud (request )).dict (exclude_none = True )
187224
188225 async def put (self , request : Request , pk : str , data : Dict [str , Any ]) -> Model :
189226 obj = await self .get_instance (request , pk )
@@ -228,87 +265,6 @@ def prefetch(
228265 queryset = field .prefetch (request , queryset )
229266 return queryset
230267
231- # @classmethod
232- # def create_model(cls, data: dict, session: Session):
233- # """
234- # 写入数据库之前调用
235- # """
236- # instance = cls.model()
237- # for k, v in data.items():
238- # field = getattr(cls.model, k)
239- # if isinstance(field.property, RelationshipProperty):
240- # if field.property.direction == MANYTOMANY:
241- # model = field.mapper.class_
242- # pk = list(get_pk(model).values())[0]
243- # childs = session.execute(select(model).where(pk.in_(v))).scalars().fetchall()
244- # setattr(instance, k, childs)
245- # # getattr(instance, k).append(*childs)
246- # elif field.property.direction == MANYTOONE:
247- # field = get_real_column_field(field)
248- # setattr(instance, field.key, v)
249- # elif field.property.direction == ONETOMANY: # todo 暂时不考虑支持
250- # # onetoone
251- # if not getattr(field.property, "uselist"):
252- # pass
253- # else:
254- # pass
255- # else:
256- # raise AttributeError(
257- # f"error relationshipfield: {cls.model}'s {field} relationship is not true."
258- # )
259- # else:
260- # setattr(instance, k, v)
261- # return instance
262- #
263- # @classmethod
264- # def update_model(cls, instance: Any, data: dict, session: Session) -> Any:
265- # """
266- # 更新数据之前调用
267- # """
268- # for k, v in data.items():
269- # field = getattr(cls.model, k)
270- # if isinstance(field.property, RelationshipProperty):
271- # if field.property.direction == MANYTOMANY:
272- # model = field.mapper.class_
273- # pk = list(get_pk(model).values())[0]
274- # childs = session.execute(select(model).where(pk.in_(v))).scalars().fetchall()
275- # setattr(instance, k, childs)
276- # elif field.property.direction == MANYTOONE:
277- # field = get_real_column_field(field)
278- # setattr(instance, field.key, v)
279- # elif field.property.direction == ONETOMANY: # todo 暂时不考虑支持
280- # # onetoone
281- # if not getattr(field.property, "uselist"):
282- # pass
283- # else:
284- # pass
285- # else:
286- # raise AttributeError(
287- # f"error relationshipfield: {cls.model}'s {field} relationship is not true."
288- # )
289- # else:
290- # setattr(instance, k, v)
291- # return instance
292-
293- # @classmethod
294- # def get_clean_fields(cls, fields, need_many: bool = False):
295- # """
296- # 获取对外键进行处理过的列表,该方法主要用于数据处理
297- # """
298- # res = []
299- # for i in fields:
300- # if hasattr(i.property, "direction"):
301- # if i.property.direction in (MANYTOMANY, ONETOMANY):
302- # if need_many:
303- # res.append(i)
304- # else:
305- # continue
306- # if i.property.direction == MANYTOONE:
307- # res.append(get_real_column_field(i))
308- # else:
309- # res.append(i)
310- # return res
311-
312268 __list_sql = None
313269
314270 def queryset (self , request : Request ):
@@ -322,6 +278,7 @@ async def list(
322278 page : int = 1 ,
323279 ):
324280 base_queryset = self .queryset (request )
281+ base_queryset = self .queryset_filter (request , base_queryset )
325282 queryset = self .prefetch (request , base_queryset , self .get_list_distplay ())
326283 datas = await queryset .limit (perPage ).offset ((page - 1 ) * perPage )
327284 res = []
@@ -340,13 +297,6 @@ async def get_instance(self, request: Request, pk: Any) -> Optional[Model]:
340297 queryset = self .prefetch (request , queryset , self .get_update_fields ())
341298 return await queryset .first ()
342299
343- # @classmethod
344- # def get_one_sql(cls, pks: list, need_many: bool = False):
345- # if cls.__one_sql is None:
346- # __list_display = cls.get_clean_fields(cls.update_fields, need_many)
347- # cls.__one_sql = select(__list_display)
348- # return cls.__one_sql.where(*pks)
349- #
350300 def make_fields (self ):
351301 if not self .fields .get ("pk" ):
352302 self .fields ["pk" ] = create_column ("pk" , self .model ._meta .pk , self .prefix )
@@ -389,6 +339,9 @@ async def select_options(
389339 perPage : Optional [int ],
390340 page : Optional [int ],
391341 ):
342+ """
343+ 外键的枚举获取值以及多对多获取对象列表
344+ """
392345 return await self .selct_defs [name ](request , pk , perPage , page )
393346
394347
0 commit comments