Django проверить, действительно ли поле для предварительной выборки - PullRequest
0 голосов
/ 13 февраля 2020

Данные модели:

class Parent:
  ...


class Child:
  parent = models.ForeignKey(Parent, on_delete=models.CASCADE)
  parent_id = models.IntegerField()

Есть ли способ проверить, что parent действительно для предварительной выборки - без фактического выполнения запроса и сбоя?

Учитывая список типа ['parent', 'parent_id'] Я хочу сделать что-то вроде: Child.prefetch_related(['parent', 'parent_id']), где он игнорирует parent_id.

1 Ответ

1 голос
/ 13 февраля 2020

Вы можете использовать приведенную ниже функцию для возврата списка предварительно выбираемых полей.

from django.db.models.base import ModelBase

def get_prefetchable_fields(instance):
    opts = instance._meta
    ret = []
    for field in opts.get_fields():
        if not isinstance(instance, ModelBase):
            rel_obj_descriptor = getattr(instance.__class__, field.name, None)
        else:
            rel_obj_descriptor = getattr(instance, field.name, None)
        if rel_obj_descriptor:
            if hasattr(rel_obj_descriptor, 'get_prefetch_queryset'):
                ret.append(field.name)
            else:
                rel_obj = getattr(instance, field.name)
                if hasattr(rel_obj, 'get_prefetch_queryset'):
                    ret.append(field.name)
    return ret

Передача модели в функцию вернет список полей ForeignKey непосредственно в модели, которую можно использовать в prefetch_related.

prefetchable = get_prefetchable_fields(Child)  # ['parent']
fields = ['parent', 'parent_id']
Child.objects.prefetch_related(*[field for field in fields if field in prefetchable])

В качестве бонуса, если вы передадите экземпляр модели, он также вернет связанные поля из другой модели.

instance = Parent.objects.first()
prefetchable = get_prefetchable_fields(instance)  # ['child_set']
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...