Reputation: 2715
Before Django 2.X I use this function for checking that ForeignKey
and OneToOneField
were prefetched to the Django model instance.
def ensure_related(obj, field):
field_obj = obj._meta.get_field(field)
if hasattr(obj, field_obj.get_cache_name()):
return True
return False
So for example
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
But since Django 2.X this method always return True
.
My questions is: how since Django 2.X implement this check?
Upvotes: 1
Views: 294
Reputation: 164
You can use fields_cache
in obj._state
(instance of ModelState)
>>> Car.objects.first()._state.fields_cache
{}
>>> Car.objects.prefetch_related('manufacturer').first()._state.fields_cache
{'manufacturer': None}
also works with lazy loading:
>>> car = Car.objects.first()
>>> car._state.fields_cache
{}
>>> car.manufacturer
>>> car._state.fields_cache
{'manufacturer': None}
so ensure_related
should be like this:
def ensure_related(obj, field):
return field in obj._state.fields_cache
Upvotes: 4