【发布时间】:2022-01-03 09:57:46
【问题描述】:
我正在编写一个 Django Rest 框架,我想使用 generics.CreateAPIView 在我的数据库中创建一个操作。
我的 models.py:
class User(AbstractBaseUser, PermissionsMixin):
uuid = models.UUIDField(primary_key=True, default=uuid.uuid4, editable=False)
email = models.EmailField("Email Address", unique=True)
first_name = models.CharField("First Name", max_length=150)
last_name = models.CharField("Last Name", max_length=150)
mobile = models.CharField("Mobile Number", max_length=150, blank=True)
balance = models.DecimalField(max_digits=9, decimal_places=2, default=0.0, verbose_name=("Balance"))
created_at = models.DateTimeField("Created at", auto_now_add=True, editable=False)
class Operation(models.Model):
sender = models.ForeignKey("User", related_name=("Sender"), on_delete=models.CASCADE)
receiver = models.ForeignKey("User", related_name=("Receiver"), on_delete=models.CASCADE)
amount = models.DecimalField(max_digits=9, decimal_places=2, default=0.0, verbose_name=("Amount"))
created_at = models.DateTimeField("Created at", auto_now_add=True, editable=False)
我想在创建操作时发送 uuid 值并使用视图在后端处理用户过滤器。 所以我在序列化器中添加了额外的字段:
class OperationCreateSerializer(serializers.ModelSerializer):
sender_uuid = serializers.UUIDField(format='hex_verbose')
receiver_uuid = serializers.UUIDField(format='hex_verbose')
amount = serializers.DecimalField(max_digits=9, decimal_places=2, coerce_to_string=False)
class Meta:
model = Operation
fields = ["sender_uuid", "receiver_uuid", "amount"]
write_only_fields = ["sender_uuid", "receiver_uuid"]
class OperationListSerializer(serializers.ModelSerializer):
class Meta:
model = Operation
fields = ["sender", "receiver", "amount"]
问题是当我尝试创建 transfert 操作时,视图中的字段 'amount' 出现错误 [<class 'decimal.InvalidOperation'>]。
我认为我使用的逻辑是:
class TransferView(generics.CreateAPIView):
serializer_class = OperationCreateSerializer
queryset = Operation.objects.all()
def create(self, request, *args, **kwargs):
serializer = OperationCreateSerializer(data=request.data)
if serializer.is_valid(raise_exception=True):
print(serializer.validated_data.get('amount'))
if serializer.is_valid(raise_exception=True):
with transaction.atomic():
sender = User.objects.filter(uuid=serializer.validated_data.get('sender_uuid'))
if sender and sender[0].balance >= serializer.validated_data.get('amount'):
User.objects.filter(uuid=serializer.validated_data.get('sender_uuid')).update(balance=F('balance') - serializer.validated_data.get('amount', 0))
User.objects.filter(uuid=serializer.validated_data.get('receiver_uuid')).update(balance=F('balance') + serializer.validated_data.get('amount', None))
serializer.save(sender=User.objects.get(uuid=serializer.validated_data.get('sender_uuid')), receiver=User.objects.get(uuid=serializer.validated_data.get('receiver_uuid')))
return Response({'message': 'transfer done successfully'}, status=status.HTTP_201_OK)
else:
return Response({'message': 'insufficient balance'}, status=status.HTTP_400_BAD_REQUEST)
return Response(status=status.HTTP_400_BAD_REQUEST)
class TransactionViewSet(generics.ListAPIView):
permission_classes = (IsAuthenticated,)
serializer_class = OperationListSerializer
queryset = Operation.objects.all()
def get_queryset(self, **kwargs):
"""
Restricting the returned purchased Operations to a given a date range query
parameter in the URL.
"""
start = self.request.query_params.get('start_date')
end = self.request.query_params.get('end_date')
try:
queryset = self.queryset.filter(Q(created_at__range=[start, end]))
return queryset
except Operation.DoesNotExist:
raise Http404
我不知道该字段的 Decimale 值有什么问题,我发现有办法映射额外字段 fields = ["sender_uuid", "receiver_uuid"] 我用来将 uuid 值发送到后端使用方法在模型fields = ["sender", "receiver"] 中的适当字段
> build_standard_field(self, field_name, model_field) 我不知道如何使用此方法以及为什么在尝试创建实例时出现错误。
编辑:
这是我得到的错误:
Internal Server Error: /v1/api/transfert/
Traceback (most recent call last):
File "/home/mohammed/Projects/PaymentSystem/paymentsys/lib/python3.7/site-packages/django/core/handlers/exception.py", line 47, in inner
response = get_response(request)
File "/home/mohammed/Projects/PaymentSystem/paymentsys/lib/python3.7/site-packages/django/core/handlers/base.py", line 181, in _get_response
response = wrapped_callback(request, *callback_args, **callback_kwargs)
File "/home/mohammed/Projects/PaymentSystem/paymentsys/lib/python3.7/site-packages/django/views/decorators/csrf.py", line 54, in wrapped_view
return view_func(*args, **kwargs)
File "/home/mohammed/Projects/PaymentSystem/paymentsys/lib/python3.7/site-packages/django/views/generic/base.py", line 70, in view
return self.dispatch(request, *args, **kwargs)
File "/home/mohammed/Projects/PaymentSystem/paymentsys/lib/python3.7/site-packages/rest_framework/views.py", line 509, in dispatch
response = self.handle_exception(exc)
File "/home/mohammed/Projects/PaymentSystem/paymentsys/lib/python3.7/site-packages/rest_framework/views.py", line 469, in handle_exception
self.raise_uncaught_exception(exc)
File "/home/mohammed/Projects/PaymentSystem/paymentsys/lib/python3.7/site-packages/rest_framework/views.py", line 480, in raise_uncaught_exception
raise exc
File "/home/mohammed/Projects/PaymentSystem/paymentsys/lib/python3.7/site-packages/rest_framework/views.py", line 506, in dispatch
response = handler(request, *args, **kwargs)
File "/home/mohammed/Projects/PaymentSystem/paymentsys/lib/python3.7/site-packages/rest_framework/generics.py", line 190, in post
return self.create(request, *args, **kwargs)
File "/home/mohammed/Projects/PaymentSystem/payment_api/account/views.py", line 30, in create
serializer.save(sender=User.objects.get(uuid=serializer.validated_data.get('sender_uuid')), receiver=User.objects.get(uuid=serializer.validated_data.get('receiver_uuid')), amount=decimal.Decimal(serializer.validated_data.get('amount')))
File "/home/mohammed/Projects/PaymentSystem/paymentsys/lib/python3.7/site-packages/django/db/models/manager.py", line 85, in manager_method
return getattr(self.get_queryset(), name)(*args, **kwargs)
File "/home/mohammed/Projects/PaymentSystem/paymentsys/lib/python3.7/site-packages/django/db/models/query.py", line 431, in get
num = len(clone)
File "/home/mohammed/Projects/PaymentSystem/paymentsys/lib/python3.7/site-packages/django/db/models/query.py", line 262, in __len__
self._fetch_all()
File "/home/mohammed/Projects/PaymentSystem/paymentsys/lib/python3.7/site-packages/django/db/models/query.py", line 1324, in _fetch_all
self._result_cache = list(self._iterable_class(self))
File "/home/mohammed/Projects/PaymentSystem/paymentsys/lib/python3.7/site-packages/django/db/models/query.py", line 68, in __iter__
for row in compiler.results_iter(results):
File "/home/mohammed/Projects/PaymentSystem/paymentsys/lib/python3.7/site-packages/django/db/models/sql/compiler.py", line 1122, in apply_converters
value = converter(value, expression, connection)
File "/home/mohammed/Projects/PaymentSystem/paymentsys/lib/python3.7/site-packages/django/db/backends/sqlite3/operations.py", line 313, in converter
return create_decimal(value).quantize(quantize_value, context=expression.output_field.context)
decimal.InvalidOperation: [<class 'decimal.InvalidOperation'>]
[03/Jan/2022 15:58:16] "POST /v1/api/transfert/ HTTP/1.1" 500 145513
【问题讨论】:
-
你能分享你的错误日志吗?
-
@P.Ezzati 我添加了错误日志。
标签: python django django-rest-framework django-views django-serializer