Получение обратного отношения в 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