Эффективный способ получения данных о взаимоотношениях
У меня есть модель ABC и поле с именем GROUP, которое является внешним ключом, и эта модель Abc также используется в качестве внешнего ключа в другой модели XYZ.
Мое требование заключается в том, что при просмотре списка XYZ с фильтрами типа (whse=«01» и abc=«02») я хочу получить название группы (из модели abc) вместе с данными списка модели XYZ.
class ABC(models.Model):
group = models.ForeignKey(Group, on_delete=models.CASCADE)
class XYZ(models.Model):
abc = models.ForeignKey(ABC, on_delete=models.CASCADE)
whse = models.ForeignKey(WHSE, on_delete=models.CASCADE)
qty = models.CharField()
Сейчас я делаю так - в сериализаторе определяю поля SerializerMethodField().
здесь код -
class XYZSerializer(serializers.ModelSerializer):
groupName = serializers.SerializerMethodField()
def get_groupName(self, instance):
return instance.abc.group.name if instance.abc else ''
class Meta:
model = ZYX
fields = '__all__'
Я получаю желаемый результат, но вы видите, что мое требование фильтра всегда (whse=«01» и abc=«02») на модели XYZ, и поэтому значение get_groupName всегда будет оставаться одинаковым для каждого моего запроса (мой abc всегда будет одинаковым в выходном списке, поэтому будет и имя группы).
Как я могу отформатировать свои данные, сериализатор, чтобы уменьшить запрос к базе данных, (чтобы найти groupName) для каждого элемента списка?
EDIT - EDIT -
вот мой взгляд
class XYZ_View(generics.ListAPIView):
permission_classes = [IsAuthenticated]
serializer_class = XYZSerializer
def get_queryset(self):
abcId = self.request.GET.get('abc')
whseId = self.request.GET.get('whse')
if abcId and whseId is not None:
qs = ZYX.objects.filter(abc = itemId, whse = whseId)
return qs
return ZYX.objects.none()
Вы получаете Group
вместе с ним .select_related(…)
[Django-doc]:
class XYZ_View(generics.ListAPIView):
permission_classes = [IsAuthenticated]
serializer_class = XYZSerializer
def get_queryset(self):
abcId = self.request.GET.get('abc')
whseId = self.request.GET.get('whse')
if abcId and whseId is not None:
return XYZ.objects.filter(abc=itemId, whse=whseId).select_related(
'abc__group'
)
return XYZ.objects.none()
Вы можете переписать сериализатор следующим образом:
class XYZSerializer(serializers.ModelSerializer):
groupName = serializers.CharField(read_only=True, source='abc.group.name')
class Meta:
model = XYZ
fields = '__all__'