How to access a serializer attribute from a method with no 'attrs' argument

Viewed 250

Im trying to access the participants attribute in my conversation serializer from inside my 'get_other_user' method. My participants attribute returns a list of user dictionaries.

However, when I run the code I get model has no attribute 'participants'. Im assuming I have to pass in a, 'attrs' argument in to the 'get_other_user' method, (one similar to the 'def validate(self, attrs) method), then use attrs.get('participants). However, I do not know how to fill in the attrs parameter when calling this method in my get_other_username method.

Any advice would be appreciates. Thanks!

class ConversationSerializer(serializers.ModelSerializer): 

    other_username = serializers.SerializerMethodField(method_name='get_other_username', read_only=True)
    other_user_email = serializers.SerializerMethodField(method_name='get_other_user_email', read_only=True)
    # latest_message = serializers.SerializerMethodField(method_name='get_latest_message', read_only=True)
    participants = UsersSerializer(many=True, read_only=True)



    class Meta:
        model = Conversation
        fields = ['conversation_id' ,'participants','other_username', 'other_user_email']

    def get_current_user_id(self):
        user_id = self.context['current_user'].id
        return user_id

     
    def get_other_user(self):
        current_user_id = self.get_current_user_id()
        for participant in self.participants:
            if participant['id'] != current_user_id:
                return participant




    def get_other_username(self, obj):
        other_user = self.get_other_user()
        return other_user['username']

    def get_other_user_email(self, obj):
        other_user = self.get_other_user()
        return other_user.email        
1 Answers

You can pass the object as a parameter to the method field function, and iterate over it. I usually use method fields with functions populating it just by using the get_{FIELD_NAME} pattern.

class ConversationSerializer(serializers.ModelSerializer):
    other_username = serializers.SerializerMethodField(read_only=True)
    participants = UsersSerializer(many=True, read_only=True)

    class Meta:
        model = Conversation
        fields = [
            "participants",
            "other_username",
        ]

    def get_current_user_id(self):
        user_id = self.context["current_user"].id
        return user_id

    def get_other_username(self, obj):
        current_user_id = self.get_current_user_id()
        for participant in obj.participants.all():
            if participant.id != current_user_id:
                return participant

This will return the first user that is not the requesting user, if you can have a conversation between more than 2 people maybe you would need to do some tinkering.

Related