Django DecimalField存入浮点数失败问题求助
问题排查:Django保存WithdrawRequests时触发ValidationError
相关代码
models.py
class WithdrawRequests(models.Model): withdraw_hash = models.CharField(max_length=255, unique=True, db_index=True) timestamp = models.DateTimeField(auto_now_add=True) username = models.CharField(max_length=255, unique=False, db_index=True) currency = models.CharField(max_length=255, unique=False, db_index=True) user_balance = models.DecimalField(max_digits=300, default=0.0, decimal_places=150) withdraw_address = models.CharField(max_length=255, unique=False, db_index=True) withdraw_amount = models.DecimalField(max_digits=30, default=0.0, decimal_places=15)
views.py 相关片段
currency = request.data['currency'] payload = jwt.decode(token, settings.SECRET_KEY) user = User.objects.get(id=payload['user_id']) timestamp = datetime.datetime.now() timestamp = timestamp.timestamp() withdraw_hash = hashlib.sha256() withdraw_hash.update(str(timestamp).encode("utf-8")) withdraw_hash = withdraw_hash.hexdigest() username = user.username currency_balance = GAME_CURRENCIES[request.data['currency']] user_balance = getattr(user, currency_balance) withdraw_address = request.data['withdraw_address'] withdraw_amount = request.data['withdraw_amount'] if user_balance < withdraw_amount: return Response({ "message": "Not enough funds." }) else: # row format - hash timestamp username currency user_balance withdraw_address withdraw_amount withdraw = WithdrawRequests() withdraw.withdraw_hash = withdraw_hash, withdraw.timestamp = datetime.datetime.now(), withdraw.username = username, withdraw.currency = currency, withdraw.user_balance = user_balance, withdraw.withdraw_address = withdraw_address, withdraw.withdraw_amount = withdraw_amount withdraw.save()
错误信息
File "C:\Users\Msi\cover_game\cover\lib\site-packages\django\db\models\fields\__init__.py", line 1554, in to_python raise exceptions.ValidationError( django.core.exceptions.ValidationError: ['“(0.011095555563904999,)” value must be a decimal number.']
错误原因
你给模型字段赋值时,每个赋值语句末尾都多写了逗号,导致实际赋值的是**元组(tuple)**而非原始数值/字符串。比如withdraw.user_balance = user_balance, 会把原本的数值包装成(0.011095555563904999,)这样的元组,而Django的DecimalField只能接受合法的小数类型(如Decimal、整数、符合格式的字符串),无法解析元组,因此抛出ValidationError。
另外补充两个优化点:
- 模型中
timestamp字段已经设置了auto_now_add=True,会自动在创建时生成时间,无需手动赋值。 withdraw_amount来自前端请求的字符串,直接赋值给DecimalField可能存在类型风险,建议转换为Decimal类型后再赋值。
修复后的代码
修改views.py中else块的赋值逻辑,去掉所有逗号,并优化timestamp和withdraw_amount的处理:
else: # 转换withdraw_amount为Decimal类型 from decimal import Decimal try: withdraw_amount = Decimal(withdraw_amount) except ValueError: return Response({"message": "Invalid withdraw amount format."}) withdraw = WithdrawRequests() withdraw.withdraw_hash = withdraw_hash # 去掉手动赋值timestamp,依赖模型的auto_now_add=True withdraw.username = username withdraw.currency = currency withdraw.user_balance = user_balance withdraw.withdraw_address = withdraw_address withdraw.withdraw_amount = withdraw_amount withdraw.save()
内容的提问来源于stack exchange,提问作者Mels Hakobyan
相关产品推荐
相关产品推荐

