Django中apps与ContentType获取模型类的区别是什么?
Django中apps模块与ContentType动态获取模型的差异
在Django开发中如果需要通过应用标签(app_label)和模型名动态获取模型类,常见有两种实现方式,二者的核心差异和适用场景如下:
实现示例
第一种:通过apps模块获取
from django.apps import apps model = apps.get_model(app_label=app_label, model_name=model_name)
第二种:通过ContentType获取
from django.contrib.contenttypes.models import ContentType model = ContentType.objects.get(app_label=app_label, model=model_name).model_class()
核心差异
- 数据来源不同:
apps.get_model直接读取Django进程启动时加载的应用注册表数据,全程是内存操作不走数据库;ContentType需要先查询django_content_type数据库表拿到对应记录,再通过model_class()方法映射到模型类。 - 依赖要求不同:
apps.get_model是Django核心内置能力,无需额外配置;ContentType依赖django.contrib.contenttypes应用,必须在INSTALLED_APPS中注册该应用并执行过迁移生成对应数据库表才能使用。 - 异常表现不同:
apps.get_model找不到对应模型时直接抛出LookupError,可通过require_ready=False参数适配应用未完全加载的场景;ContentType查询时如果找不到对应记录会抛出ContentType.DoesNotExist异常,就算查到记录,若当前进程未加载对应模型,model_class()会返回None。 - 性能差异明显:
apps.get_model是纯内存查询,无IO开销速度极快;ContentType有一次数据库查询开销,性能远低于前者。 - 参数规则不同:
apps.get_model的model_name参数对大小写不敏感;ContentType存储的模型名是全小写,查询时参数大小写不匹配会查不到结果。
适用场景
- 优先选择
apps.get_model的场景:- 仅需要单纯获取模型类,无泛型关联、内容类型权限等相关需求
- 对性能要求高,不想产生额外数据库查询
- 代码运行在Django启动阶段(比如AppConfig的
ready()方法),此时数据库可能未就绪无法查询 - 项目未开启
contenttypes应用
- 优先选择ContentType的场景:
- 已经持有ContentType实例(比如使用了GenericForeignKey泛型外关联),需要直接获取关联的模型类
- 业务逻辑本身依赖contenttypes生态,比如泛型关联、内容类型维度的权限控制、跨应用数据关联等
- 需要获取模型对应的content_type_id用于存储或关联查询
注意事项
- 两种方式都要求目标模型所属的应用已在
INSTALLED_APPS中注册,且模型已被Django加载完成 - 针对代理模型的场景:
apps.get_model可直接获取到代理模型;ContentType默认只会存储原始模型的记录,代理模型需要单独配置才会生成对应的ContentType记录
内容的提问来源于stack exchange,提问作者Mohammad Javad Shamloo
相关产品推荐
相关产品推荐

