Получение обратного отношения в Django Serializer

Модели:

class MaterialRequest(models.Model):

    owner = models.ForeignKey(User, on_delete=models.CASCADE, related_name='owner')
    linked = models.CharField(max_length=50, default="-", blank=True, null=True)
    flows = models.ManyToManyField(MaterialRequestFlow)
    is_allocated = models.BooleanField(default=False)
    delivery_required_on = models.DateTimeField(default=datetime.now)
    raised_by = models.CharField(max_length=1000, default="__________", blank=True, null=True)
    created_at = models.DateTimeField(auto_now_add=True)

class Allotment(models.Model):

    transaction_no = models.IntegerField(default=0)
    sales_order = models.ForeignKey(MaterialRequest, on_delete=models.CASCADE)
    is_delivered = models.BooleanField(default=False)
    document_available = models.BooleanField(default=False)

Теперь, чтобы показать мою таблицу запроса материала, я делаю что-то вроде этого:

class MREmpTableAPIView(APIView):
    permission_classes = (permissions.IsAuthenticated, MRViewPermission)

    def get(self, request, *args, **kwargs):
        items = MaterialRequest.objects.all().order_by('-id')
        serializer = EMaterialRequestTableListSerializer(items, many=True)
        return Response(serializer.data, status=status.HTTP_201_CREATED)

Где я получаю все детали заявок на материалы, но я также хочу показать transaction_no выделение linked в таблице заявок на материалы. Как мне это сделать?

Прямой способ решить эту проблему - использовать SerializerMethodField следующим образом:

class EMaterialRequestTableListSerializer(serializers.ModelSerializer):
    owner = serializers.SlugRelatedField(read_only=True, slug_field='full_name')
    transaction_no = serializers.SerializerMethodField()

    class Meta:
        model = MaterialRequest
        exclude = ('flows',)

    def get_transaction_no(self, obj)
        allotment = obj.allotment_set.first()
        return allotment.transaction_no if allotment else None

Но это попытается обратиться к базе данных для каждого MaterialRequest экземпляра, чтобы получить соответствующие выделения.

Чтобы сделать это более эффективным, вы можете предварительно получить соответствующие выделения для каждого материального запроса следующим образом:

items = MaterialRequest.objects.all().order_by('-id').prefetch_related('allotment_set')

А затем сделайте что-то вроде этого в вашем сериализаторе:

class EMaterialRequestTableListSerializer(serializers.ModelSerializer):
    owner = serializers.SlugRelatedField(read_only=True, slug_field='full_name')
    transaction_no = serializers.SerializerMethodField()

    class Meta:
        model = MaterialRequest
        exclude = ('flows',)

    def get_transaction_no(self, obj)
        if obj.allotment_set.all():
            return obj.allotment_set.all()[0].transaction_no
        return None
Вернуться на верх