1

I'm trying to create a combined viewset that displays data in a nested format from three django models.

I'm receiving an error when I try to return the viewset.

Got AttributeError when attempting to get a value for field `runner` on serializer `CombinedSerializer`. The serializer field might be named incorrectly and not match any attribute or key on the `Runner` instance. Original exception text was: 'Runner' object has no attribute 'runner'.

serializers.py

class CombinedSerializer(serializers.Serializer):
    event = EventSerializer()
    market = MarketSerializer()
    runner = RunnerSerializer()
    class Meta:
        fields = ('event' , 'market', 'runner')

views.py

class CombinedViewSet(mixins.ListModelMixin, 
                      viewsets.GenericViewSet, 
                     mixins.RetrieveModelMixin):

    queryset = Runner.objects.all()
    serializer_class = CombinedSerializer

models.py

class Event(models.Model):
    sport_id = models.CharField(max_length=15)
    event_id = models.BigIntegerField(unique=True)
    event_name = models.CharField(max_length=200)
    start_time = models.DateTimeField(null=True)
    status = models.CharField(max_length=13)


class Market(models.Model):
    event = models.ForeignKey(Event, on_delete=models.CASCADE)
    market_id = models.BigIntegerField(unique=True)
    market_name = models.CharField(max_length=35)
    status = models.CharField(max_length=10)
    volume = models.FloatField(null=True)

class Runner(models.Model):
    event = models.ForeignKey(Event, null=True, default=None, on_delete=models.CASCADE)
    market = models.ForeignKey(Market, null=True, default=None, on_delete=models.CASCADE)
    runner_id = models.BigIntegerField(unique=True)
    name = models.CharField(max_length=500)
    back_odds = models.FloatField(null=True)
    lay_odds = models.FloatField(null=True)

For some reason when I remove runner from the serializer Event and Market display in my api in nested format. When I add Runner I get the above error. How can I fix this and display all three in my API?

6
  • 1
    The serializer thinks that "Combined Serializer" is serializing the "Runner" model. Becuase "Runner" is the queryset. Try taking runner out, but then rather listing all the fields that you want from your runner model in the "fields" tuple. Commented Nov 23, 2019 at 9:31
  • @Neil If I add the fields from runner model in fields tuple how does the serializer know that those fields belong to the runner model since it's not referenced? I've taken out runner and tried to add the fields and I don't get any data from runners back in the api response. Commented Nov 23, 2019 at 9:37
  • It is referenced behind the scenese. DRF does quite a lot. When the view calls the serializer it passes in the queryset. Do you get an error, or do you just not get any data? Commented Nov 23, 2019 at 9:39
  • @Neil I've no idea to be honest. I don't normally work with DRF. I got no data and no error Commented Nov 23, 2019 at 9:41
  • Add your models, so we can help you with the setup of the viewset/serializer Commented Nov 23, 2019 at 10:15

1 Answer 1

1

The quesryset in the ViewSet contains the Runner instances:

queryset = Runner.objects.all()

But in the CombinedSerializer you have included the runner field (mapped to the RunnerSerailizer) -- you already have a Runner model instance so you don't have runner field in there, you only have the fields that are available in the Runner model, any reverse-related fields, and custom fields that you've added on the serializer.


You have a couple of options:

Inherit from ModelSerializer and include all the fields:

class CombinedSerializer(serializers.ModelSerializer):
    event = EventSerializer()
    market = MarketSerializer()

    class Meta:
        model = Runner
        fields = '__all__'

Or if you want more granular control over your fields, mention the fields explicitly (you can keep the Serializer inheritence in this case) e.g.:

class CombinedSerializer(serializers.Serializer):
    event = EventSerializer()
    market = MarketSerializer()

    class Meta:
        fields = ('event', 'market', 'name', 'back_odds')

If you want to inherit from serializers.ModelSerializer, you need to mention the model in the Meta class:

class CombinedSerializer(serializers.ModelSerializer):
    event = EventSerializer()
    market = MarketSerializer()

    class Meta:
        model = Runner
        fields = ('event', 'market', 'name', 'back_odds')
Sign up to request clarification or add additional context in comments.

Comments

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.