2

I'm trying to get the same output as my django query but the actual output differs when Django Rest Framework serves it. Added the following to my serializer but it kept leaving out the cart_assessments__risk_type out of the output. How do I make my django rest framework serializer output match my django query output?

models.py:

from django.db import models

class TrainAssessment(models.Model):
    train_name = models.CharField(max_length=30)


class CartAssessment(models.Model):
    train_assessment = models.ForeignKey(TrainAssessment, on_delete=models.CASCADE, related_name='cart_assessments')
    risk_type = models.CharField(max_length=30)

views.py

from rest_framework import viewsets, mixins

class SubwayTrainDetailsViewSet(viewsets.GenericViewSet,
                            mixins.ListModelMixin,
                            mixins.CreateModelMixin):
    queryset = TrainAssessment.objects.values('cart_assessments__risk_type').annotate(
        cart_count=Count('cart_assessments__risk_type')).order_by('-cart_count').annotate(
        train_count=Count('id', distinct=True))
    serializer_class = serializers.SubwayTrainDetailsViewSetSerializer

serializers.py

from rest_framework import serializers

class SubwayTrainDetailsViewSetSerializer(serializers.ModelSerializer):
    train_count = serializers.IntegerField()
    cart_count = serializers.IntegerField()
    cart_assessments__risk_type = serializers.RelatedField(source="cartassessment.risk_type", read_only=True)

    class Meta:
        model = TrainAssessment
        fields = ('id', 'cart_assessments__risk_type', 'train_count', 'cart_count')

Im trying to make my serializer provide the same output as below:

#QUERY
queryset = TrainAssessment.objects.values('cart_assessments__risk_type').annotate(
    cart_count=Count('cart_assessments__risk_type')).order_by('-cart_count').annotate(
    train_count=Count('id', distinct=True))

#OUTPUT I WANT THAT COMES FROM ABOVE QUERY:
{'cart_assessments__risk_type': '', 'cart_count': 55, 'train_count': 14}
{'cart_assessments__risk_type': 'door', 'cart_count': 22, 'train_count': 13}
{'cart_assessments__risk_type': 'wheel', 'cart_count': 8, 'train_count': 8}
{'cart_assessments__risk_type': 'frame', 'cart_count': 1, 'train_count': 1}
{'cart_assessments__risk_type': 'floors', 'cart_count': 1, 'train_count': 1}
{'cart_assessments__risk_type': 'windows', 'cart_count': 1, 'train_count': 1}
{'cart_assessments__risk_type': 'straphanger', 'cart_count': 1, 'train_count': 1}

Actual Output missing cart_assessments__risk_type from Django Rest Framework when hitting the endpoint/route for SubwayTrainDetailsViewSet:

# OUTPUT MISSING `cart_assessments__risk_type`
[
    {"train_count": 14, "cart_count": 55},
    {"train_count": 13, "cart_count": 22},
    {"train_count": 8, "cart_count": 8},
    {"train_count": 1, "cart_count": 1},
    {"train_count": 1, "cart_count": 1},
    {"train_count": 1, "cart_count": 1},
    {"train_count": 1,"cart_count": 1}
]

How can I django rest framework serve the output with cart_assessments__risk_type?p

  • 2
    What about this? `cartassessment__risk_type = serializers.CharField(source='cartassessment__risk_type')` ? – tarasinf Mar 04 '20 at 06:22
  • 1
    You've lost `s` in the end of the relation name. – Ivan Starostin Mar 04 '20 at 06:33
  • @tarasinf when trying that I get the following error `It is redundant to specify `source='cartassessment__risk_type'` on field 'CharField' in serializer 'SubwayTrainDetailsViewSetSerializer', because it is the same as the field name. Remove the `source` keyword argument.` – Daniel Plas Rivera Mar 04 '20 at 10:04
  • @IvanStarostin when trying with the `s` in the source in `RelatedField`, it did not mention any errors but still didn't show the `cart_assessments__risk_type` in the output – Daniel Plas Rivera Mar 04 '20 at 10:08
  • 2
    @DanielPlasRivera quick solution, try by method in serializer, like `def get_cart_assessments` – tarasinf Mar 04 '20 at 13:35

1 Answers1

2

Thanks @tarasinf . I was able to come up with the answer with that solution you mentioned.

class SubwayTrainDetailsViewSetSerializer(serializers.ModelSerializer):
    train_count = serializers.IntegerField()
    cart_count = serializers.IntegerField()
    cart_assessments__risk_type = serializers.SerializerMethodField('get_cart_assessments')

    class Meta:
        model = TrainAssessment
        fields = ('cart_assessments__risk_type', 'train_count', 'cart_count')

    def get_cart_assessments(self, obj):
        return obj.get('cart_assessments__risk_type')