Skip to content
Advertisement

DRF: How to pass extra context data to serializers

I was searching the net and found the similar problem but it doesn’t work in my case, Idk why. I try to put some extra data to context in serializer, but get only 3 default fields: request, view and format and no mention for my custom data.

My model:

class Match(models.Model):

sender = models.ForeignKey(
    Client,
    on_delete=models.CASCADE,
    related_name='senders'
)
recipient = models.ForeignKey(
    Client,
    on_delete=models.CASCADE,
    related_name='recipients'
)

class Meta:
    app_label = 'clients'
    db_table = 'matches'
    verbose_name = 'match'
    verbose_name_plural = 'matches'
    constraints = [
        models.UniqueConstraint(
            fields=['sender', 'recipient'],
            name='unique_match'
        )
    ]

My Serializer:

class MatchSerializer(serializers.ModelSerializer):

sender = serializers.HiddenField(default=serializers.CurrentUserDefault())

def validate(self, data):
    if data['sender'] == self.context['recipient']:
        raise serializers.ValidationError('You cannot match yourself')
    return data

def create(self, validated_data):

    return Match.objects.create(
        sender=validated_data['sender'],
        recipient=self.context['recipient']
    )

class Meta:
    model = Match
    fields = ['sender']`

My ModelViewSet:

class MatchMVS(ModelViewSet):
    queryset = Match.objects.all()
    serializer_class = MatchSerializer
    http_method_names = ['post']
    permission_classes = [IsAuthenticated]

    # without and with doesn't work
    def get_serializer_context(self):
        context = super(MatchMVS, self).get_serializer_context()
        context.update({
            "recipient": Client.objects.get(pk=23)
            # extra data
        })
        return context

    @action(detail=True, methods=['POST'], name='send_your_match')
    def match(self, request, pk=None):
        sender = request.user
        recipient = Client.objects.get(pk=pk)
        serializer = MatchSerializer(context={'request': request, 'recipient': recipient},
                                     data=request.data)

        data_valid = serializer.is_valid(raise_exception=True)
        if data_valid:
            recipient = serializer.save()

        is_match = Match.objects.filter(sender=recipient, recipient=sender).exists()
        if is_match:
            send_mail(
                f'Hello, {sender.first_name}',
                f'You got match with {recipient.first_name}! '
                f'Your`s partner email: {recipient.email}',
                settings.EMAIL_HOST_USER,
                [sender.email],
                fail_silently=False,
            )
            send_mail(
                f'Hello, {recipient.first_name}',
                f'You got match with {sender.first_name}! '
                f'Your`s partner email: {sender.email}',
                settings.EMAIL_HOST_USER,
                [recipient.email],
                fail_silently=False,
            )

            return Response(recipient.email, 201)
        else:
            return Response(f'Your sympathy has been sent to {recipient.username}.', 201)

I was debugging it through PyCharm and Postman but still can’t understand where is my mistake. Hope you will help me to fix it.

Advertisement

Answer

Your code is right.It should work. But i don’t know where is the issue.You can try the modified code as below.

class MatchSerializer(serializers.ModelSerializer):

    def validate(self, data):
        if data['sender'] == data['recipient']:
            raise serializers.ValidationError('You cannot match yourself')
        return data
    class Meta:
        model = Match

        fields = ['sender', 'recipient']

class MatchMVS(ModelViewSet):
    queryset = Match.objects.all()
    serializer_class = MatchSerializer
    http_method_names = ['post']
    permission_classes = [IsAuthenticated]

    @action(detail=True, methods=['POST'], name='send_your_match')
    def match(self, request, pk=None):
        sender = request.user
        recipient = Client.objects.get(pk=pk)
        serializer = MatchSerializer(data={**request.data, 'recipient': recipient.id})

        data_valid = serializer.is_valid(raise_exception=True)
        if data_valid:
            recipient = serializer.save()

        is_match = Match.objects.filter(sender=recipient, recipient=sender).exists()
        if is_match:
            send_mail(
                f'Hello, {sender.first_name}',
                f'You got match with {recipient.first_name}! '
                f'Your`s partner email: {recipient.email}',
                settings.EMAIL_HOST_USER,
                [sender.email],
                fail_silently=False,
            )
            send_mail(
                f'Hello, {recipient.first_name}',
                f'You got match with {sender.first_name}! '
                f'Your`s partner email: {sender.email}',
                settings.EMAIL_HOST_USER,
                [recipient.email],
                fail_silently=False,
            )

            return Response(recipient.email, 201)
        else:
            return Response(f'Your sympathy has been sent to {recipient.username}.', 201)
User contributions licensed under: CC BY-SA
4 People found this is helpful
Advertisement