Как ограничить сериализацию в Django Rest Framework?

У меня есть 2 сериализатора, которые добавляют и вычитают (они одинаковые, с разницей в том, что add +=1 и subtract -=1) точки к ответу. Я хочу ограничить их так, чтобы пользователь мог использовать add point к ответу только один раз. Есть ли у вас идеи, как добраться до этого в Django Rest Framework?

class Answer(models.Model):
    number_of_points = models.IntegerField(default=0)

class SubtractPointsSerializer(serializers.ModelSerializer):
    class Meta:
        model = Answer
        fields = ('number_of_points',)

    def update(self, instance, validated_data):

        instance.number_of_points -= 1
        instance.save()
        return instance
Internal Server Error: /api/v1/answers/2/addpoints
Traceback (most recent call last):
  File "/Library/Frameworks/Python.framework/Versions/3.7/lib/python3.7/site-packages/django/core/handlers/exception.py", line 47, in inner
    response = get_response(request)
  File "/Library/Frameworks/Python.framework/Versions/3.7/lib/python3.7/site-packages/django/core/handlers/base.py", line 179, in _get_response
    response = wrapped_callback(request, *callback_args, **callback_kwargs)
  File "/Library/Frameworks/Python.framework/Versions/3.7/lib/python3.7/site-packages/django/views/decorators/csrf.py", line 54, in wrapped_view
    return view_func(*args, **kwargs)
  File "/Library/Frameworks/Python.framework/Versions/3.7/lib/python3.7/site-packages/django/views/generic/base.py", line 70, in view
    return self.dispatch(request, *args, **kwargs)
  File "/Library/Frameworks/Python.framework/Versions/3.7/lib/python3.7/site-packages/rest_framework/views.py", line 509, in dispatch
    response = self.handle_exception(exc)
  File "/Library/Frameworks/Python.framework/Versions/3.7/lib/python3.7/site-packages/rest_framework/views.py", line 469, in handle_exception
    self.raise_uncaught_exception(exc)
  File "/Library/Frameworks/Python.framework/Versions/3.7/lib/python3.7/site-packages/rest_framework/views.py", line 480, in raise_uncaught_exception
    raise exc
  File "/Library/Frameworks/Python.framework/Versions/3.7/lib/python3.7/site-packages/rest_framework/views.py", line 506, in dispatch
    response = handler(request, *args, **kwargs)
  File "/Library/Frameworks/Python.framework/Versions/3.7/lib/python3.7/site-packages/rest_framework/generics.py", line 226, in put
    return self.update(request, *args, **kwargs)
  File "/Library/Frameworks/Python.framework/Versions/3.7/lib/python3.7/site-packages/rest_framework/mixins.py", line 68, in update
    self.perform_update(serializer)
  File "/Library/Frameworks/Python.framework/Versions/3.7/lib/python3.7/site-packages/rest_framework/mixins.py", line 78, in perform_update
    serializer.save()
  File "/Library/Frameworks/Python.framework/Versions/3.7/lib/python3.7/site-packages/rest_framework/serializers.py", line 200, in save
    self.instance = self.update(self.instance, validated_data)
  File "/Users/jakubstrawa/programming/gitlabdeor/api/questions/serializers.py", line 74, in update
    if not instance.addition_done and self.request.user not in instance.voters.all():
AttributeError: 'AddPointsSerializer' object has no attribute 'request'

Вы всегда можете добавить поле Boolean, которое хранит, было ли произведено сложение/вычитание. Вы можете хранить все User, которые уже голосовали, так что никто не будет голосовать дважды (также не будет голосовать за оба +1/-1).

class Answer(models.Model):
    number_of_points = models.IntegerField(default=0)
    addition_done = models.BooleanField(default=False)
    subtraction_done = models.BooleanField(default=False)
    voters = models.ManyToManyField('User', default=None, blank=True)

===========================================================

class SubtractPointsSerializer(serializers.ModelSerializer):
    ...

    def update(self, instance, validated_data):
        if not instance.subtraction_done:
            instance.number_of_points -= 1
            instance.subtraction_done = True
        instance.save()
        return instance

Вы также можете разделить поле ManyToMany на два отдельных (одно для сложения, другое для вычитания).

Вернуться на верх