Как правильно десериализовать данные с помощью django-money?

У меня есть Model, которая содержит MoneyField из djmoney

class Task(models.Model):
    description = models.CharField(max_length=512)
    user = models.ForeignKey("user.User", on_delete=models.CASCADE)
    price = MoneyField(
        max_digits=8,
        decimal_places=2,
        default_currency="USD",
        default=0)

Сериализатор

class TaskSerializer(serializers.ModelSerializer):
    class Meta:
        model = Task
        fields = "__all__"
        read_only_fields = ("user",)

Мой APIView POST функция Viewset

    def create(self, request, *args, **kwargs):
        serializer = self.get_serializer(data=request.data)
        serializer.is_valid(raise_exception=True)
        self.perform_create(serializer)
        headers = self.get_success_headers(serializer.data)
        return Response(serializer.data, status=201, headers=headers)

    def perform_create(self, serializer):
        serializer.save(user=self.request.user)

Когда я пытаюсь отправить данные в формате, подобном этому

{
    "description": "Test",
    "price": "20.00"
}

Выдает ошибку, что у объекта 'decimal.Decimal' нет атрибута 'amount' с заданным Traceback.

Как я могу решить эту проблему?

Traceback (most recent call last):
  File "/home/user/.virtualenvs/my_project/lib/python3.10/site-packages/django/core/handlers/exception.py", line 55, in inner
    response = get_response(request)
  File "/home/user/.virtualenvs/my_project/lib/python3.10/site-packages/django/core/handlers/base.py", line 197, in _get_response
    response = wrapped_callback(request, *callback_args, **callback_kwargs)
  File "/home/user/.virtualenvs/my_project/lib/python3.10/site-packages/django/views/decorators/csrf.py", line 54, in wrapped_view
    return view_func(*args, **kwargs)
  File "/home/user/.virtualenvs/my_project/lib/python3.10/site-packages/rest_framework/viewsets.py", line 125, in view
    return self.dispatch(request, *args, **kwargs)
  File "/home/user/.virtualenvs/my_project/lib/python3.10/site-packages/rest_framework/views.py", line 509, in dispatch
    response = self.handle_exception(exc)
  File "/home/user/.virtualenvs/my_project/lib/python3.10/site-packages/rest_framework/views.py", line 469, in handle_exception
    self.raise_uncaught_exception(exc)
  File "/home/user/.virtualenvs/my_project/lib/python3.10/site-packages/rest_framework/views.py", line 480, in raise_uncaught_exception
    raise exc
  File "/home/user/.virtualenvs/my_project/lib/python3.10/site-packages/rest_framework/views.py", line 506, in dispatch
    response = handler(request, *args, **kwargs)
  File "/home/user/PycharmProjects/my_project/tackapp/tack/views.py", line 37, in create
    serializer.is_valid(raise_exception=True)
  File "/home/user/.virtualenvs/my_project/lib/python3.10/site-packages/rest_framework/serializers.py", line 227, in is_valid
    self._validated_data = self.run_validation(self.initial_data)
  File "/home/user/.virtualenvs/my_project/lib/python3.10/site-packages/rest_framework/serializers.py", line 426, in run_validation
    value = self.to_internal_value(data)
  File "/home/user/.virtualenvs/my_project/lib/python3.10/site-packages/rest_framework/serializers.py", line 483, in to_internal_value
    validated_value = field.run_validation(primitive_value)
  File "/home/user/.virtualenvs/my_project/lib/python3.10/site-packages/rest_framework/fields.py", line 569, in run_validation
    self.run_validators(value)
  File "/home/user/.virtualenvs/my_project/lib/python3.10/site-packages/rest_framework/fields.py", line 593, in run_validators
    validator(value)
  File "/home/user/.virtualenvs/my_project/lib/python3.10/site-packages/djmoney/models/validators.py", line 30, in __call__
    cleaned = cleaned.amount

Я нашел обходной путь, но я пытаюсь сделать свой код чистым и простым. И мне кажется, что я что-то упускаю. То есть, по сути, сериализатор ожидает значение в объекте Money, но не ожидает str от собственных методов сериализатора

    def create(self, request, *args, **kwargs):
        price = Money(request.data["price"], "USD")
        serializer = self.get_serializer(data=request.data | {"price": price})
        ...
Вернуться на верх