11import datetime
2- import logging
32import re
43from enum import Enum
54from typing import (
1918from fastapi import APIRouter , Body , Depends , Query
2019from fastapi .encoders import DictIntStrAny , SetIntStr
2120from pydantic import Extra , Json
21+ from pydantic .fields import ModelField
2222from sqlalchemy import Column , Table , delete , func , insert
2323from sqlalchemy .future import select
2424from sqlalchemy .orm import InstrumentedAttribute , Session
4242 SQLModelField ,
4343 SQLModelFieldParser ,
4444 SQLModelListField ,
45+ SQLModelPropertyField ,
4546 get_python_type_parse ,
4647)
4748from .schema import BaseApiOut , ItemListSchema
@@ -228,11 +229,15 @@ def calc_filter_clause(self, data: Dict[str, Any]) -> List[BinaryExpression]:
228229class SQLModelCrud (BaseCrud , SQLModelSelector ):
229230 engine : SqlalchemyDatabase = None
230231 create_fields : List [SQLModelField ] = [] # 新增数据字段
231- readonly_fields : List [SQLModelListField ] = [] # 只读字段
232- """readonly fields, deprecated, not recommended, will be removed in version 0.4.0"""
233- update_fields : List [SQLModelListField ] = [] # 可编辑字段
232+ readonly_fields : List [SQLModelListField ] = []
233+ """readonly fields, priority is higher than update_fields.
234+ readonly fields, deprecated, not recommended, will be removed in version 0.4.0"""
235+ update_fields : List [SQLModelPropertyField ] = []
236+ """model update fields;support model property and relationship field."""
234237 update_exclude : Optional [Union [SetIntStr , DictIntStrAny ]] = None
235- """update exclude fields, such as: {'id', 'key', 'name'} or {'id': True, 'category': {'id', 'name'}}"""
238+ """update exclude fields, such as: {'id', 'key', 'name'} or {'id': True, 'category': {'id', 'name'}}."""
239+ read_fields : List [SQLModelPropertyField ] = []
240+ """Model read fields; used in route_read, note the difference between readonly_fields and read_fields."""
236241
237242 def __init__ (
238243 self ,
@@ -246,11 +251,11 @@ def __init__(
246251 self .db = get_engine_db (self .engine )
247252 SQLModelSelector .__init__ (self , model , fields )
248253 BaseCrud .__init__ (self , self .model , router )
249- if self .readonly_fields :
250- logging .warning (
251- "readonly fields, deprecated, not recommended, will be removed in version 0.4.0."
252- "Please replace them with update_fields and update_exclude."
253- )
254+ # if self.readonly_fields:
255+ # logging.warning(
256+ # "readonly fields, deprecated, not recommended, will be removed in version 0.4.0."
257+ # "Please replace them with update_fields and update_exclude."
258+ # )
254259
255260 def _create_schema_list (self ) -> Type [SchemaListT ]:
256261 if self .schema_list :
@@ -296,6 +301,15 @@ def _create_schema_filter(self) -> Type[SchemaFilterT]:
296301 set_none = True ,
297302 )
298303
304+ def _create_schema_read (self ) -> Type [SchemaReadT ]:
305+ if self .schema_read :
306+ return self .schema_read
307+ if not self .read_fields :
308+ return super ()._create_schema_read ()
309+ self .read_fields = self .parser .filter_insfield (self .read_fields , save_class = (ModelField ,))
310+ modelfields = [self .parser .get_modelfield (ins , deepcopy = True ) for ins in self .read_fields ]
311+ return schema_create_by_modelfield (f"{ self .schema_name_prefix } Read" , modelfields , orm_mode = True )
312+
299313 def _create_schema_update (self ) -> Type [SchemaUpdateT ]:
300314 if self .schema_update :
301315 return self .schema_update
@@ -340,7 +354,7 @@ def _fetch_item_scalars(self, session: Session, item_id: List[str]) -> List[Mode
340354 stmt = select (self .model ).where (self .pk .in_ (list (map (get_python_type_parse (self .pk ), item_id ))))
341355 return session .scalars (stmt ).all ()
342356
343- def _read_items (self , session : Session , item_id : List [str ]):
357+ def _read_items (self , session : Session , item_id : List [str ]) -> List [ SchemaReadT ] :
344358 items = self ._fetch_item_scalars (session , item_id )
345359 return [self .read_item (obj ) for obj in items ]
346360
0 commit comments