'Filter on nested serializer in django rest framework

I'm building a serializer in django using the django rest framework. I need to filter the query set for a nested model.

I found How do you filter a nested serializer in Django Rest Framework?, which seemed to have the answer, but when I implemented it there was no change in my data. The only difference I can see is that the serializer referencing the filtered list serializer has other fields as well.

The models (abbreviated for clarity):

class GCUser(models.Model):
    first_name = models.CharField(max_length=50)
    last_name = models.CharField(max_length=50)
    email = models.EmailField()
    is_member = models.BooleanField(default=False)
    age = models.SmallIntegerField(blank=True, null=True)
    session_key = models.CharField(max_length=100, db_index=True, blank=True, null=True)


class Connection(models.Model):
    creation_date = models.DateTimeField(auto_now_add=True)
    user = models.ForeignKey(GCUser, related_name='user_connection')
    event = models.ForeignKey(Event, related_name='event_connection')
    role = models.CharField(max_length=8, choices=constants.Roles.ROLE_CHOICES,)

class Event(Game):
    creation_date = models.DateTimeField(auto_now_add=True)
    public = models.BooleanField(default=False)
    start_time = models.DateTimeField(null=True, blank=True)
    end_time = models.DateTimeField(null=True, blank=True)
    gm_is_player = models.BooleanField(default=False,
                                       help_text='Check if GM will be playing the game',
                                       verbose_name='GM is a player')
    gm_is_designer = models.BooleanField(default=False, help_text='Check if GM designed the game')
    user_notes = models.TextField(blank=True, default='', verbose_name='Note to Scheduler')
    scheduler_notes = models.TextField(blank=True, default='')
    experience = models.CharField(max_length=3, choices=constants.ExpLevels.EXPERIENCE_CHOICES,
                                  default=constants.ExpLevels.NOVICE,)
    status = models.CharField(max_length=4, db_index=True,
                              choices=constants.Status.STATUS_CHOICES,)

Here's my code:

class FilteredListSerializer(serializers.ListSerializer):
    def to_representation(self, data):
        data = data.filter(status=constants.Status.ASSIGNED).order_by('start_time')
        return super(FilteredListSerializer, self).to_representation(data)


class UserEventSerializer(serializers.ModelSerializer):
    class Meta:
        list_serializer_class = FilteredListSerializer
        model = models.Event
        fields = ('id', 'event_name', 'conflict_type', 'start_time', 'end_time')


class UserConnectionSerializer(serializers.ModelSerializer):
    event = UserEventSerializer()

    class Meta:
        model = models.Connection
        fields = ('get_role_display', 'conflict_type', 'event')


class GCUserSerializer(serializers.ModelSerializer):
    user_connection = UserConnectionSerializer(many=True)

    class Meta:
        model = models.GCUser
        fields = ('pk', 'first_name', 'last_name', 'email',
                  'is_member', 'age', 'user_connection')

PyCharm tells me that "class FilteredListSerializer must implement all abstract methods" but it doesn't actually throw an error. I put a breakpoint at the first line of the list serializer, but it doesn't get tripped.

I'm using Python 3.4 with django 1.7.

Thanks in advance for your help.

Edited to add: Looking into the serializer code, I realized what may be the key difference: my call has many=True, whereas the one from the previous post didn't. I tried taking out the model=, but as expected that threw an error, so apparently the "working" code in the earlier post didn't actually run as written.



Solution 1:[1]

So I am not sure how to use the method you are using, but, if I understand your question correctly, I believe you could do something like this:

  class UserEventSerializer(serializers.ModelSerializer):
    class Meta:
      model = models.Event
      fields = ('id', 'event_name', 'conflict_type', 'start_time', 'end_time')

  class UserConnectionSerializer(serializers.ModelSerializer):
    event = serializers.SerializerMethodField()

    class Meta:
        model = models.Connection
        fields = ('get_role_display', 'conflict_type', 'event')

    def get_event(self, obj):
      if obj.event.status == constants.Status.ASSIGNED:
        serializer = UserEventSerializer(obj.event)
        return serializer.data
      else:
        serializer = UserEventSerializer(None)
        return serializer.data

N.B. This assumes that you are trying to exclude Events from being serialized if their status is not assigned.

I hope this helps. If I didn't understand the problem, let me know.

Solution 2:[2]

it's not a bug or error. ModelSerializer has got already implemented all needed methods (most inhereted from Serializer class), but ListSerializer inherits from BaseSerializer and got implemented e.g.: .create() or .to_representation(), but not .update(). I've got some similar problems in PyCharm, when subclassing a Serializer. After implementing create, update and to_representation methods this issue was gone

Sources

This article follows the attribution requirements of Stack Overflow and is licensed under CC BY-SA 3.0.

Source: Stack Overflow

Solution Source
Solution 1
Solution 2 noumen