i have a a problem deleting an object via API. So i have 2 models, Answer and Vote vote is connected to Answer via foreignKey like this
class Vote(models.Model):
class AnswerScore(models.IntegerChoices):
add = 1
subtract = -1
score = models.IntegerField(choices=AnswerScore.choices)
answer = models.ForeignKey('Answer', on_delete=models.PROTECT)
user = models.ForeignKey('users.CustomUser', on_delete=models.PROTECT)
class Meta:
unique_together = ('answer', 'user',)
class Answer(models.Model):
answer = models.TextField()
created_at = models.DateTimeField(editable=False, default=timezone.now)
updated_at = models.DateTimeField(default=timezone.now)
user = models.ForeignKey('users.CustomUser', on_delete=models.PROTECT)
question = models.ForeignKey('Question', on_delete=models.PROTECT)
number_of_points = models.IntegerField(default=0)
moderate_status = models.BooleanField(default=False)
Now i have an API endpoint for creating a Vote for user on a particular answer
path('answers/<int:pk>/vote', VoteCreate.as_view()),
Looks like this:
class VoteSerializer(serializers.ModelSerializer):
user = serializers.PrimaryKeyRelatedField(read_only=True, default=serializers.CurrentUserDefault())
answer = serializers.PrimaryKeyRelatedField(read_only=True)
class Meta:
model = Vote
fields = '__all__'
class VoteCreate(ParentKeyAPIView, generics.CreateAPIView):
model = Vote
parent_model_field = 'answer_id'
serializer_class = VoteSerializer
def perform_create_kwargs(self, **kwargs):
answer_id = self.kwargs['pk']
answer = Answer.objects.get(id=int(answer_id))
if Vote.objects.filter(user=self.request.user, answer=answer).exists():
old_vote = Vote.objects.get(user=self.request.user, answer=answer)
answer -= old_vote.score
answer.save()
old_vote.delete()
return super().perform_create_kwargs(user=self.request.user, answer_id=answer_id, **kwargs)
Im using the same serializer just like above*
I get an error: Not Found: /api/v1/answers/55/voteDelete There is no any traceback, i have checked in fact that in database the Vote with answer_id 55 exists and i can delete them via django-admin but cant via API. Do you have any idea why?
CodePudding user response:
First thing - let's change get_queryset to get_object, because you want single object. Then instead of answer_id=self.kwargs['pk'] simplify it to answer=self.kwargs['pk'].
Another thing - I think it's might be better to delete old vote while creating new one. You don't need serializer or special view for that. Just add to function creating new Vote object in your view:
class VoteCreate(...):
...
def perform_create_kwargs(self, **kwargs):
answer_id = self.kwargs['pk']
answer = Answer.object.get(id=int(answer_id))
if Vote.objects.filter(user=self.request.user, answer=answer).exists():
old_vote = Vote.objects.get(user=self.request.user, answer=answer)
answer -= old_vote.score
answer.save()
old_vote.delete()
return super().perform_create_kwargs(user=self.request.user, answer_id=answer_id, **kwargs)
