首页 > 解决方案 > 如何检查 Django 模型实例是否已预选相关数据

问题描述

在 Django 2.XI 之前,使用此函数进行检查ForeignKeyOneToOneField预取到 Django 模型实例。

def ensure_related(obj, field):
    field_obj = obj._meta.get_field(field)

    if hasattr(obj, field_obj.get_cache_name()):
        return True
    return False

所以例如

In [1]: permission = Permission.objects.last()

SELECT "auth_permission"."id",
       "auth_permission"."name",
       "auth_permission"."content_type_id",
       "auth_permission"."codename"
  FROM "auth_permission"
 INNER JOIN "django_content_type"
    ON ("auth_permission"."content_type_id" = "django_content_type"."id")
 ORDER BY "django_content_type"."app_label" DESC,
          "django_content_type"."model" DESC,
          "auth_permission"."codename" DESC
 LIMIT 1


In [2]: ensure_related(permission, 'content_type')

Out[2]: False

In [3]: permission = Permission.objects.prefetch_related('content_type').last()

SELECT "auth_permission"."id",
       "auth_permission"."name",
       "auth_permission"."content_type_id",
       "auth_permission"."codename"
  FROM "auth_permission"
 INNER JOIN "django_content_type"
    ON ("auth_permission"."content_type_id" = "django_content_type"."id")
 ORDER BY "django_content_type"."app_label" DESC,
          "django_content_type"."model" DESC,
          "auth_permission"."codename" DESC
 LIMIT 1


SELECT "django_content_type"."id",
       "django_content_type"."app_label",
       "django_content_type"."model"
  FROM "django_content_type"
 WHERE "django_content_type"."id" IN (1)


In [3]: ensure_related(permission, 'content_type')

Out[4]: True

但是从 Django 2.X 开始,这个方法总是返回True.

我的问题是:自从 Django 2.X 以来如何实现这个检查?

标签: pythondjango

解决方案


您可以fields_cacheobj._stateModelState的实例)中使用

>>> Car.objects.first()._state.fields_cache
{}

>>> Car.objects.prefetch_related('manufacturer').first()._state.fields_cache
{'manufacturer': None}

也适用于延迟加载:

>>> car = Car.objects.first()
>>> car._state.fields_cache
{}
>>> car.manufacturer
>>> car._state.fields_cache
{'manufacturer': None}

所以ensure_related应该是这样的:

def ensure_related(obj, field):
    return field in obj._state.fields_cache

推荐阅读