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.
CodePudding user response:
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)
CodePudding user response:
The problem was my own inattention, the wrong viewset was linked to the url
urlpatterns = [
path('clients/<int:pk>/match', views.MatchCreateAPIView.as_view(), name='get_match')
]
instead of:
urlpatterns = [
path('clients/<int:pk>/match', views.MatchMVS.as_view({'post': 'match'}), name='get_match')
]