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)