Django多事务转账报错:UserBalanceChange与int无法执行+运算
Django多用户转账功能报错修复
问题说明
在Django中实现多用户转账:买家支付的金额按80%分给卖家,20%分给管理员。仅涉及两位用户时代码正常运行,加入第三位用户后触发错误:Error 'unsupported operand type(s) for +: 'UserBalanceChange' and 'int''。
现有代码
views.py
from django.db import transaction from django.http import HttpResponse from django.shortcuts import render from .models import UserBalanceChange @transaction.atomic() def transaction_file(request): if request.method == "POST": try: buyer = request.POST.get('buyer') seller = request.POST.get('seller') admin = request.POST.get('admin') amount = request.POST.get('amount') buyer_obj = UserBalanceChange.objects.get(user=buyer) seller_obj = UserBalanceChange.objects.get(user=seller) admin_obj = UserBalanceChange.objects.get(user=admin) with transaction.atomic(): buyer_obj.amount -= int(0.8*int(amount)) buyer_obj.save() seller_obj.amount += int(0.8*int(amount)) seller_obj.save() with transaction.atomic(): buyer_obj.amount -= int(0.2 * int(amount)) buyer_obj.save() admin_obj = admin_obj + int(0.2 * int(amount)) admin_obj.save() return HttpResponse('Транзакция успешно проведена') except Exception as e: print(e) return HttpResponse('Что-то пошло не так!(') return render(request,'chat/files/chattransaction.html')
models.py
from django.db import models from django.contrib.auth.models import User from django.utils import timezone class UserBalanceChange(models.Model): user = models.ForeignKey(User,on_delete = models.CASCADE, related_name='balance_changes') amount = models.DecimalField(verbose_name='Amount', default=0, max_digits=18, decimal_places=2) datetime = models.DateTimeField(verbose_name='date', default=timezone.now) def __str__(self): return f'{self.user.username}'
HTML模板
<form method="POST" style="width: 50%;"> {% csrf_token %} <form method="post"> <div class="form-group"> <label>Покупатель</label> <input class="form-control" name="buyer" type="text" placeholder="Покупатель"> </div> <div class="form-group"> <label>Продавец</label> <input class="form-control" name="seller" type="text" placeholder="Продавец"> </div> <div class="form-group"> <label>Админ</label> <input class="form-control" name="admin" type="text" placeholder="Админ"> </div> <div class="form-group"> <label>Цена</label> <input class="form-control" name="amount" type="text" placeholder="Цена"> </div> <button type="submit" class="btn btn-primary">Купить</button> </form> </form>
错误原因
报错行admin_obj = admin_obj + int(0.2 * int(amount))中,admin_obj是UserBalanceChange模型实例,不能直接与整数相加。正确操作应该是修改实例的amount属性,和前面处理买家、卖家余额的逻辑一致。
另外还有两处优化点:
- 嵌套的
transaction.atomic()无必要,外层已经用装饰器开启了原子事务,所有操作会作为一个整体提交/回滚。 - 用
int()处理金额会丢失精度,建议用Decimal类型计算,匹配模型中的DecimalField。
修正后的代码
修正后的views.py
from django.db import transaction from django.http import HttpResponse from django.shortcuts import render from decimal import Decimal from .models import UserBalanceChange @transaction.atomic() def transaction_file(request): if request.method == "POST": try: buyer = request.POST.get('buyer') seller = request.POST.get('seller') admin = request.POST.get('admin') amount = Decimal(request.POST.get('amount')) buyer_obj = UserBalanceChange.objects.get(user=buyer) seller_obj = UserBalanceChange.objects.get(user=seller) admin_obj = UserBalanceChange.objects.get(user=admin) # 计算分配金额 seller_amount = amount * Decimal('0.8') admin_amount = amount * Decimal('0.2') # 扣减买家余额 buyer_obj.amount -= amount buyer_obj.save() # 增加卖家余额 seller_obj.amount += seller_amount seller_obj.save() # 增加管理员余额 admin_obj.amount += admin_amount admin_obj.save() return HttpResponse('Транзакция успешно проведена') except Exception as e: print(e) return HttpResponse('Что-то пошло не так!(') return render(request,'chat/files/chattransaction.html')
修正后的HTML模板(移除嵌套form)
<form method="POST" style="width: 50%;"> {% csrf_token %} <div class="form-group"> <label>Покупатель</label> <input class="form-control" name="buyer" type="text" placeholder="Покупатель"> </div> <div class="form-group"> <label>Продавец</label> <input class="form-control" name="seller" type="text" placeholder="Продавец"> </div> <div class="form-group"> <label>Админ</label> <input class="form-control" name="admin" type="text" placeholder="Админ"> </div> <div class="form-group"> <label>Цена</label> <input class="form-control" name="amount" type="text" placeholder="Цена"> </div> <button type="submit" class="btn btn-primary">Купить</button> </form>
内容的提问来源于stack exchange,提问作者Xrystik
相关产品推荐
相关产品推荐

