Определите, был ли объект, связанный с Django, предварительно получен с помощью select_related
Допустим, у меня есть следующие модели:
class Product:
name = models.CharField(max_length=128)
class ProductVersion:
name = models.CharField(max_length=128)
product = models.ForeignKey(Product, on_delete=models.CASCADE)
Для данного объекта ProductVersion
можно ли как-то определить, был ли объект Product
префетчен через select_related
? Например:
# Yes, "product" was prefetched
ProductVersion.objects.select_related("product").first()
# No, "product" was NOT prefetched
ProductVersion.objects.first()
Похоже, что есть способ сделать это для prefetch_related
(см. здесь), но мне это нужно для selected_related
.
Вы можете сделать это с помощью проверки JOIN
слова в запросе
queryset = ProductVersion.objects.select_related("product")
sql_query = str(queryset.query) # convert ORM query to SQL query
if 'JOIN' in sql_query:
print("Product object was prefetched via select_related")
else:
print("Product object was NOT prefetched via select_related")
Нет специального способа проверить, было ли поле заполнено благодаря select_related
, но если ваша цель - проверить, приведет ли обращение к полю к запросу к базе данных, вы можете проверить, кэшировано поле или нет, используя метод is_cached
на его дескрипторе:
cached_obj = ProductVersion.objects.select_related("product").first()
noncached_obj = ProductVersion.objects.first()
print(ProductVersion.product.is_cached(cached_obj)) # True
# OR in case you don't want to use the model class directly
print(cached_obj._meta.model.product.is_cached(cached_obj)) # True
print(ProductVersion.product.is_cached(noncached_obj)) # False
# OR in case you don't want to use the model class directly
print(noncached_obj._meta.model.product.is_cached(noncached_obj)) # False