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

Django钱包交易后如何修改Product模型关联用户、实现交易追踪与余额校验

现存代码问题点
  • 校验逻辑顺序倒置:当前代码先执行余额扣减、加账操作,之后才校验付款方/收款方是否为同一用户,触发异常时已经产生了账户余额被修改的脏数据
  • 缺失余额不足拦截:没有对比付款方账户余额与交易金额的逻辑,会出现账户余额被扣成负数的非法交易
  • 缺失核心购买逻辑:交易完成后没有更新Product表的关联用户字段,没有实现商品所有权转移的目标
  • 无交易留痕机制:所有余额划转操作没有持久化存储,管理员无法回溯全量交易记录
  • 无事务保护:多步数据库操作没有事务包裹,任意一步出错都会导致数据不一致
分模块改造实现

Model层新增交易追溯能力

在原有models.py中新增交易流水模型,用于记录全量交易动作,满足管理员后台追溯要求:

class TransactionRecord(models.Model):
    sender = models.ForeignKey(User, on_delete=models.CASCADE, related_name="send_records")
    receiver = models.ForeignKey(User, on_delete=models.CASCADE, related_name="receive_records")
    related_product = models.ForeignKey(Product, on_delete=models.SET_NULL, null=True, blank=True, verbose_name="关联交易商品")
    amount = models.FloatField(verbose_name="交易金额")
    created_at = models.DateTimeField(auto_now_add=True, verbose_name="交易时间")
    status = models.CharField(max_length=20, default="success", verbose_name="交易状态")
    fail_reason = models.CharField(max_length=255, null=True, blank=True, verbose_name="失败原因")

    def __str__(self):
        return f"{self.sender.username} 转给 {self.receiver.username} | 金额 {self.amount}"

在admin.py中注册该模型,即可在管理员后台直接查看、检索所有交易记录,不需要额外写后台页面:

from django.contrib import admin
from .models import TransactionRecord
admin.site.register(TransactionRecord)

View层逻辑修正

调整原有buy_c视图的执行顺序,补全校验、所有权转移、事务保护、交易留痕逻辑:

from django.db import transaction as db_transaction

def buy_c(request, ok):
    ctp_val = Product.objects.get(id=ok)
    msg = "Enter Details"
    if request.method == "POST":
        # 开启数据库事务,所有操作要么全部生效,要么全部回滚,避免脏数据
        with db_transaction.atomic():
            try:
                username = request.POST["username"]
                amount = float(request.POST["amount"])
                sender_user = request.user
                receiver_user = User.objects.get(username=username)
                sender_balance = Balance.objects.get(user=sender_user)
                receiver_balance = Balance.objects.get(user=receiver_user)

                # 前置校验环节,不通过直接抛异常触发事务回滚
                # 1. 禁止自转账
                if sender_user == receiver_user:
                    raise Exception("无法向自己发起交易")
                # 2. 余额不足拦截
                if sender_balance.balance < amount:
                    raise Exception("账户余额不足,无法完成支付")
                # 3. 禁止购买自己已持有的商品
                if ctp_val.user == sender_user:
                    raise Exception("无法购买自己持有的商品")

                # 校验全部通过后再执行余额变更
                sender_balance.balance -= amount
                receiver_balance.balance += amount
                sender_balance.save()
                receiver_balance.save()

                # 核心业务逻辑:将商品所有权转移到付款方
                ctp_val.user = sender_user
                ctp_val.transection_id += 1
                ctp_val.save()

                # 写入成功交易流水
                TransactionRecord.objects.create(
                    sender=sender_user,
                    receiver=receiver_user,
                    related_product=ctp_val,
                    amount=amount,
                    status="success"
                )

                msg = "Transaction Success"
                return redirect("/user")

            except Exception as e:
                # 事务自动回滚,不会产生余额错扣的脏数据
                # 写入失败交易记录,方便后续排障追溯
                try:
                    TransactionRecord.objects.create(
                        sender=request.user,
                        receiver=User.objects.get(username=request.POST.get("username", "")),
                        related_product=ctp_val,
                        amount=float(request.POST.get("amount", 0)),
                        status="failed",
                        fail_reason=str(e)
                    )
                except:
                    pass
                msg = f"交易失败:{str(e)}"
    
    context = {"coin": ctp_val, "msg": msg}
    return render(request, 'coinwall.html', context)

模板端适配

原有coinwall.html不需要做结构改动,原有{{msg}}变量会自动渲染所有校验失败、交易成功的提示信息,readonly的输入框也可以正常展示收款方账号、交易金额,避免用户手动篡改交易参数。

内容的提问来源于stack exchange,提问作者sr freak

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.10.26 16:15:06