Ответ 1
ДОРОГИЕ ДРУЗЬЯ ИЗ БУДУЩЕГО: на момент написания статьи команда Django REST Framework, похоже, работает над добавлением более зрелой поддержки общих отношений. Но это еще не закончено. Прежде чем копировать этот ответ в базу кода, сначала проверьте https://github.com/tomchristie/django-rest-framework/pull/755, чтобы узнать, объединено ли оно с репо. Возможно, вас ждет более элегантное решение. - Ваш древний предок Тайлер
Учитывая, что вы используете Django REST Framework, если вы хотите сделать некоторую пост-обработку (даже если вы, похоже, не решаетесь), вы можете добиться чего-то своей цели переопределяя get_queryset
или list
в вашем представлении. Что-то вроде этого:
views.py:
from rest_framework.generics import ListAPIView
from rest_framework.response import Response
from models import *
from itertools import chain
class ResultsList(ListAPIView):
def list(self, request, *args, **kwargs):
nurses = Nurse.objects.all()
pilots = Pilot.objects.all()
results = list()
entries = list(chain(nurses, pilots)) # combine the two querysets
for entry in entries:
type = entry.__class__.__name__.lower() # 'nurse', 'pilot'
if isinstance(entry, Nurse):
serializer = NurseSerializer(entry)
hospital = serializer.data['hospital']
enrollement_date = serializer.data['enrollement.date']
hq = serializer.data['enrollement.hq']
dictionary = {'type': type, 'hospital': hospital, 'hq': hq, 'enrollement_date': enrollement_date}
if isinstance(entry, Pilot):
serializer = PilotSerializer(entry)
plane = serializer.data['plane']
enrollement_date = serializer.data['enrollement.date']
hq = serializer.data['enrollement.hq']
dictionary = {'type': type, 'plane': plane, 'hq': hq, 'enrollement_date': enrollement_date}
results.append(dictionary)
return Response(results)
serializers.py
class EnrollementSerializer(serializer.ModelSerializer):
class Meta:
model = Enrollement
fields = ('hq', 'enrollement_date')
class NurseSerializer(serializer.ModelSerializer):
enrollement = EnrollementSerializer(source='enrollement.get')
class Meta:
model = Nurse
fields = ('hospital', 'enrollement')
class PilotSerializer(serializer.ModelSerializer):
enrollement = EnrollementSerializer(source='enrollement.get')
class Meta:
model = Pilot
fields = ('plane', 'enrollement')
Возвращенный ответ будет выглядеть так:
[
{
type: "nurse",
hq: "http://url/to/hq-detail/view",
enrollement_date: "2003-01-01 01:01:01",
hospital: "http://url/to/hospital-detail/view"
},
{
type: "pilot",
hq: "http://url/to/hq-detail/view",
enrollement_date: "2003-01-01 01:01:01",
plane: "http://url/to/plane-detail/view"
},
]
Обращает на себя внимание:
- Мой serializers.py может быть немного отсюда, потому что моя память о том, как представлять общие отношения в сериализаторах, немного туманна. YMMV.
- Аналогично ^^ это предполагает, что ваш serializers.py в порядке и правильно установил свои общие отношения в соответствии с вашими моделями.
- Мы делаем
get
вsource=enrollement.get
, потому что иначе объект GenericRelatedObjectManager будет возвращен, если мы не укажем источник. Это потому, что это то, что представляет собой общее отношение. Использование.get
заставляет запрос (как в запросе QuerySet), который обращается к модели, которую вы задали как источник общего отношения (в этом случаеclass Enrollement(models.Model)
. - Мы должны использовать
list(chain())
вместо оператора|
, потому что наборы запросов поступают из разных моделей. Вот почему мы не можем сделатьentries = nurses | pilots
. -
for entry in entries
можно сделать более сухим. GLHF.