Django实现交易模型户名同步与账户号转账功能方案咨询
解决方案:账户名同步与转账功能实现
一、账户名同步功能实现
方案1:使用pre_save信号自动同步
利用Django模型信号,在Transaction记录保存前自动根据account_number匹配账户所有者名称,无需在视图/表单中重复编写逻辑:
from django.db.models.signals import pre_save from django.dispatch import receiver from .models import Transaction, AccountNum @receiver(pre_save, sender=Transaction) def sync_transaction_account_name(sender, instance, **kwargs): # 根据输入的账户号查找对应账户记录 try: target_account = AccountNum.objects.get(account_number=instance.account_number) # 同步账户所有者名称(这里假设User模型用username作为名称,可根据实际字段调整) instance.name = target_account.user.username except AccountNum.DoesNotExist: # 处理账户不存在的异常情况,可根据业务需求调整 instance.name = "未知账户"
注意:需要确保信号被正确注册,可在应用的apps.py中添加信号导入,或者在models.py文件末尾导入信号模块。
方案2:在视图/表单层手动处理
如果不想依赖信号,可在创建Transaction的业务逻辑中直接处理名称同步,适合需要更灵活控制的场景:
from django.shortcuts import get_object_or_404 from django.utils import timezone from .models import Transaction, AccountNum def create_transaction(request): if request.method == 'POST': account_num = request.POST.get('account_number') amount = request.POST.get('amount') # 查找目标账户,不存在则返回404 target_account = get_object_or_404(AccountNum, account_number=account_num) # 创建Transaction并同步账户名称 Transaction.objects.create( user=request.user, account_number=account_num, name=target_account.user.username, amount=amount, created_on=timezone.now() ) # 后续逻辑...
二、转账功能实现
转账涉及两个用户钱包余额的修改,必须保证操作的原子性,避免并发场景下的数据不一致,推荐使用Django的事务机制:
from django.db import transaction from django.utils import timezone from decimal import Decimal from django.http import HttpResponse from .models import Transaction, AccountNum, Wallet def handle_transfer(request): if request.method == 'POST': target_account_num = request.POST.get('account_number') transfer_amount = Decimal(request.POST.get('amount')) # 原子事务:所有操作要么全部成功,要么全部回滚 with transaction.atomic(): # 获取当前用户的钱包,不存在则自动创建 sender_wallet, _ = Wallet.objects.get_or_create(user=request.user) # 检查余额是否充足 if sender_wallet.account_balance < transfer_amount: return HttpResponse("余额不足,无法完成转账", status=400) # 查找目标账户对应的用户 try: target_account = AccountNum.objects.get(account_number=target_account_num) receiver_user = target_account.user except AccountNum.DoesNotExist: return HttpResponse("目标账户不存在", status=404) # 获取接收方钱包,不存在则自动创建 receiver_wallet, _ = Wallet.objects.get_or_create(user=receiver_user) # 修改双方余额 sender_wallet.account_balance -= transfer_amount sender_wallet.save() receiver_wallet.account_balance += transfer_amount receiver_wallet.save() # 创建转账记录 Transaction.objects.create( user=request.user, account_number=target_account_num, name=receiver_user.username, amount=transfer_amount, created_on=timezone.now() ) return HttpResponse("转账成功")
关键注意事项:
- 必须使用
transaction.atomic()包裹核心逻辑,防止中途出错导致数据异常 - 处理金额时要使用
Decimal类型,避免浮点数精度问题 - 可在Wallet模型的
account_balance字段添加MinValueValidator(0),从模型层限制余额不能为负
内容的提问来源于stack exchange,提问作者Adamu Abdulkarim Dee
相关产品推荐
相关产品推荐

