Django объединяет множество несвязанных моделей по связанному внешнему ключу
У меня есть 3 модели T, E, Q такие, что:
class E(Model):
name_e = CharField()
class T(Model):
name_t = CharField()
e = ForeignKey(E)
class Q(Model):
name_q = CharField()
e = ForeignKey(E)
У меня также есть сериализаторы для каждого:
class ESerializer(ModelSerializer):
class Meta:
model = E
fields = '__all__'
class TSerializer(ModelSerializer):
e = ESerializer()
class Meta:
model = E
fields = '__all__'
class QSerializer(ModelSerializer):
e = ESerializer()
class Meta:
model = E
fields = '__all__'
На одну строку E может приходиться много строк T и Q. Я могу составить такой запрос, что
t = T.objects.filter(e__id=1).all()
serialized_t = TSerializer(t, many=True).data
И вывод serialized_t
будет выглядеть примерно так:
[
{id:7, name_t:'test_1', e:{id:1, name_e:'ename_1'}},
{id:9, name_t:'test_2', e:{id:1, name_e:'ename_1'}}
]
Мой вопрос в том, как я могу объединить их так, чтобы я мог включить Q в запрос выше, чтобы создать вывод для запроса T, который также будет включать все Q, где e_id=1, и, следовательно, это будет выглядеть примерно так:
[
{id:7, name_t:'test_1', e:{id:1, name_e:'ename_1'}, q:[{id:4, name_q:'qname_1'}, {id:5, name_q:'qname_2'}]},
{id:9, name_t:'test_2', e:{id:1, name_e:'ename_1'}, q:[{id:4, name_q:'qname_1'}, {id:5, name_q:'qname_2'}]}
]
Я не возражаю, если это можно сделать в самом запросе, или если это требует некоторого добавления к объекту SerializedT, пока у меня есть сериализованный результат в конце, который соответствует моим потребностям, который я могу отправить как объект JSON в качестве ответа API.
Это можно сделать, написав T
сериализатор следующим образом:
class TSerializer(ModelSerializer):
e = ESerializer()
q = QInTSerializer(source='e.q_set', many=True)
class Meta:
model = T
fields = '__all__'
Это создаст поле q
, которое представляет собой список объектов Q
. Указание source='e.q_set'
служит для указания полю, где искать этот список Q
из сериализуемого экземпляра T
(в данном случае, все Q
, относящиеся к T
к E
).
Но вы также должны написать еще один сериализатор Q
, чтобы не отображать E
внутри Q
(только id
и name_q
, как требуется):
class QInTSerializer(ModelSerializer):
class Meta:
model = Q
fields = ('id', 'name_q')
Вы также можете сэкономить на обращениях к БД, если планируете сериализовать несколько T
объектов, выбрав связанный E
объект и предварительно получив связанные Q
объекты из E
:
t = T.objects.select_related('e').prefetch_related('e__q_set')