You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

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

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.08.10 21:55:23