CakePHP迁移Django:如何替换get_declared_classes()为Python实现
Django迁移场景下替代PHP
get_declared_classes()的实现方案 你不需要额外找第三方库实现PHP get_declared_classes()的等价能力,结合你贴的代码逻辑和实际排查结果——原代码真正遍历的是所有已加载的CakePHP模型类,get_declared_classes()只是做类是否已加载的校验,用Django原生能力就能完美适配,完全解决手动维护类列表在不同页面不一致的问题。
原代码逻辑本质
你贴的PHP代码核心目标不是获取进程内全量已加载类,而是筛选出所有已加载的、定义了hrbc_cols或hrbc_cols_arr属性的模型类,根据请求的resource自动拼接接口拉取的字段列表。如果硬要实现全量已加载类扫描,反而会拿到大量Django内置类、第三方依赖类,和你的业务逻辑无关,徒增性能消耗。
可直接落地的实现
- 用Django官方提供的
apps.get_models()方法获取所有已注册、已加载完成的项目模型类,这个方法的返回结果完全匹配原代码中App::objects('Model')+get_declared_classes()校验后的有效类列表,Django启动完成后全局统一,不管在哪个页面、哪个视图调用,返回结果都一致,不需要手动维护类清单。 - 遍历模型时直接通过类属性判断是否存在
hrbc_cols/hrbc_cols_arr配置,和原PHP逻辑完全对齐。
对应改写后的Python代码如下:
from django.apps import apps from django.utils.text import capfirst class HrbcConnect: def __init__(self): self.scope = '' self.token = None self.token_expire = 0 self.request_opt = {} self.id = None self.id_arr = [] self.write_error = None def read(self, resource, condition='', field=None, order=None): if field is None: field = [] target_resource = capfirst(resource) # 替代原代码get_declared_classes + App::objects('Model')逻辑 for model_class in apps.get_models(include_auto_created=False): # 匹配hrbc_cols属性逻辑 hrbc_cols = getattr(model_class, 'hrbc_cols', None) if isinstance(hrbc_cols, dict) and target_resource in hrbc_cols: for col_def in hrbc_cols[target_resource]: if isinstance(col_def, (list, tuple)): field.append(col_def[0]) else: field.append(col_def) continue # 匹配hrbc_cols_arr属性逻辑 hrbc_cols_arr = getattr(model_class, 'hrbc_cols_arr', None) if isinstance(hrbc_cols_arr, dict): for cols_map in hrbc_cols_arr.values(): if not isinstance(cols_map, dict) or target_resource not in cols_map: continue for col_def in cols_map[target_resource]: if isinstance(col_def, (list, tuple)): col_name = col_def[0] if col_name not in field: field.append(col_name) else: if col_def not in field: field.append(col_def) # 后续补充接口请求、token校验等原有逻辑即可 # pass
额外说明
不要使用遍历sys.modules、递归查找类子类的方案实现类扫描,这类方案要么会漏掉延迟导入的模型,要么会扫入大量无关类,稳定性和性能都不如Django官方提供的模型注册接口。如果需要过滤部分不需要扫描的模型,直接给对应模型加自定义标记属性,遍历的时候过滤即可,扩展比原PHP实现更灵活。
内容的提问来源于stack exchange,提问作者Vinay Kumar
相关产品推荐
相关产品推荐

