如何将字符串转为Django模型类以调用filter()方法(非重复问题)
解决字符串模型名转模型类的问题
场景还原
你现在的问题是手里拿着字符串形式的模型名(比如model_name = "MyModel"),直接调用model_name.objects.filter()会报AttributeError: 'str' object has no attribute 'objects',因为字符串不是模型类对象。之前试的exec(model_name)、input(model_name)、[model_name]都没效果,而且不想用apps.get_model(),也不想写一堆if-elif匹配。
可行方案
方案1:利用全局变量字典 globals()
如果你的模型已经提前导入到当前全局作用域里,直接从globals()字典里取就行:
model_name = "MyModel" # 从全局命名空间中获取对应的模型类 model_class = globals().get(model_name) if model_class: # 现在可以正常调用objects方法了 queryset = model_class.objects.filter(...) else: # 处理模型名不存在的情况,比如抛个提示 print(f"模型 {model_name} 未找到")
注意:如果当前全局作用域里有和模型名同名的其他变量,可能会取错,所以这个方法适合模型名唯一且确定在全局的场景。
方案2:结合模块和getattr()(更推荐)
如果你的模型都集中在某个模块里(比如myapp.models),先导入模块,再用getattr()拿对应的类:
from myapp import models # 替换成你的模型所在模块 model_name = "MyModel" # 从指定模块中获取模型类,第三个参数是找不到时的默认值 model_class = getattr(models, model_name, None) if model_class: queryset = model_class.objects.filter(...) else: print(f"模型 {model_name} 在模块中不存在")
这个方法更安全,因为限定了模块范围,不会误拿到其他同名变量,也符合Django模型的常规组织方式。
为什么之前的方法无效?
exec(model_name):只是执行字符串代码,比如exec("MyModel")并不会返回模型类,就算改成exec(f"model_class = {model_name}")也有安全风险,不建议用。input(model_name):这是用来接收用户输入的函数,和转换模型类完全无关。[model_name]:只是把字符串放进列表,本质还是字符串,不是模型类对象。
内容的提问来源于stack exchange,提问作者CODComputerAtWar
相关产品推荐
相关产品推荐

