Django: выбор столбцов в разных приложениях с одним и тем же внешним ключом
Это последующий вопрос из этого.
У меня app1/models.py:
class A(models.Model):
id = models.IntegerField(primary_key=True)
text = models.CharField(max_length=20)
class B(models.Model):
fid = models.ForeignKey(A, models.CASCADE)
text = models.CharField(max_length=20)
class C(models.Model):
fid = models.ForeignKey(A, models.CASCADE)
text = models.CharField(max_length=20)
и app2/models.py:
from app1.models import A
class D(models.Model):
fid = models.ForeignKey(A, models.CASCADE)
text = models.CharField(max_length=20)
Я хочу получить A.text B.text C.text D.text где A.id == B.fid == C.fid == D.fid == 1. Из приведенного вопроса я смог получить первые 3 столбца, используя:
B.objects.filter(fid=1).values('text', 'fid__text', 'fid__c__text') # B.text, A.text, C.text
Однако я не могу получить D.text с помощью этого запроса. Я знаю, что могу сделать фильтр на D и вычислить его вручную, но я надеюсь на более Djangoic способ.
(В случае многократного совпадения, просуммируйте строки, таким образом, если в B есть 2 строки, которые соответствуют данному fid и 3, 4 для C, D, всего будет возвращено 24 строки)
Попробовать запрос из A модели
A.objects.filter(id=1).values('text', 'b__text', 'c__text', 'd__text')
Я не знаю, почему это не работает. Может быть, это ошибка базы данных? В этом случае Django может быть не при чем. Работает ли это, если заменить fid__c__text на fid__d__text?
Я бы инстинктивно запросил экземпляр модели A, который является "родителем" остальных. Получив экземпляр a, он предлагает b_set.all(), c_set.all() и d_set.all(). Для эффективности работы БД вы можете предварительно получить все связанные объекты с помощью
a = A.objects.prefetch_related('b', 'c', 'd').get( pk=b.fid_id )
(Обратите внимание, что при предварительной выборке фильтрация осуществляется путем итерации по a.b_set.all(), а не путем применения .filter(criteria), который снова попадет в БД независимо от предварительной выборки).