储蓄应用中如何在确认后提交Django客户存款表单?
解决储蓄应用存款确认表单提交失败的问题
问题描述
我正在开发一款储蓄应用,希望在显示确认表单后让用户添加客户存款。目前存款功能可正常显示确认信息,但点击确认表单上的确认按钮后,无法提交存款表单,反而跳转回存款表单,并提示amount字段不能为空。
现有代码
Model代码
class Deposit(models.Model): customer = models.ForeignKey(Customer, on_delete=models.CASCADE, null=True) acct = models.CharField(max_length=6, null=True) staff = models.ForeignKey(User, on_delete=models.CASCADE, null=True) deposit_amount = models.PositiveIntegerField(null=True) date = models.DateTimeField(auto_now_add=True) def get_absolute_url(self): return reverse('create_account', args=[self.id]) def __str__(self): return f'{self.customer} Deposited {self.deposit_amount} by {self.staff.username}'
Form代码
class CustomerDepositForm(forms.ModelForm): class Meta: model = Deposit fields = ['deposit_amount']
Views代码
def customer_deposit(request, id): context = {} form = CustomerDepositForm(request.POST or None) #Set Page Title page_title = "Customer Deposit" #Get Current Date current_date = datetime.now().date() #Get Current Month Name from Calendar current_month_name = calendar.month_name[date.today().month] try: #Check the Customer ID in DB customer = Customer.objects.get(id=id) #Customer Account acct = customer.account_number except Customer.DoesNotExist: messages.error(request, 'Customer Does Not Exist') return redirect('customer_create') else: #Get the Customer total deposit deposit = Deposit.objects.filter(customer_id = id).aggregate(total=Sum('deposit_amount') )['total'] or Decimal() if request.method == 'POST': #Deposit Form form = CustomerDepositForm(request.POST or None) if form.is_valid(): amount = form.cleaned_data['deposit_amount'] context.update( { 'deposit':deposit, 'page_title':page_title, 'customer':customer, 'current_date':current_date, 'current_month_name':current_month_name, 'form':form, 'amount':amount, 'acct':acct, }) return render(request, 'dashboard/deposit_approval_form.html', context) else: form = CustomerDepositForm() context = { 'deposit':deposit, 'page_title':page_title, 'customer':customer, 'current_date':current_date, 'current_month_name':current_month_name, 'form':form, 'acct':acct, } return render(request, 'dashboard/deposit.html', context) def approve_deposit(request, id): user = request.user form = CustomerDepositForm(request.POST or None) amount = form.cleaned_data['deposit_amount'].value() try: #Check the Customer ID in DB customer = Customer.objects.get(id=id) #Customer Account acct = customer.account_number except Customer.DoesNotExist: messages.error(request, 'Customer Does Not Exist') return redirect('customer_create') else: if request.method == 'POST': #Create Customer Deposit credit_acct = Deposit.objects.create(customer=customer, acct=acct, staff=user, deposit_amount=amount) credit_acct.save() messages.success(request, f'N{amount} Credited for Account {acct} Successfully.') return redirect('deposit-slip') else: form = CustomerDepositForm() return render(request, 'dashboard/deposit_approval_form.html')
Deposit Approval Template代码
<form method="POST"> {% csrf_token %} <a class="btn btn-secondary" href="{% url 'create-deposit' customer.id %}">Cancel</a> <input class="btn btn-danger" type="submit" value="Confirm"> </form>
问题诊断
- 确认表单未携带amount数据:当前确认表单仅包含CSRF令牌和提交按钮,未存储用户之前输入的存款金额,导致POST请求中缺失
deposit_amount字段,触发表单验证错误。 - approve_deposit视图逻辑错误:直接尝试获取
form.cleaned_data['deposit_amount'].value(),未先验证表单有效性,且未处理GET请求场景,易引发异常。 - 上下文传递未被有效利用:虽customer_deposit视图将amount传入确认页面,但模板未生成提交所需的字段。
解决方案
1. 修改确认表单模板,添加隐藏字段传递金额
在deposit_approval_form.html中添加隐藏字段存储存款金额,并指定表单提交的目标视图:
<form method="POST" action="{% url 'approve-deposit' customer.id %}"> {% csrf_token %} <!-- 隐藏字段存储用户输入的存款金额 --> <input type="hidden" name="deposit_amount" value="{{ amount }}"> <a class="btn btn-secondary" href="{% url 'create-deposit' customer.id %}">Cancel</a> <input class="btn btn-danger" type="submit" value="Confirm"> </form>
2. 修复approve_deposit视图逻辑
调整视图代码,先验证表单有效性,简化客户查询逻辑,处理异常情况:
from django.shortcuts import render, redirect, get_object_or_404 from django.contrib import messages from .models import Deposit, Customer from .forms import CustomerDepositForm def approve_deposit(request, id): user = request.user # 直接获取客户,不存在则返回404页面 customer = get_object_or_404(Customer, id=id) acct = customer.account_number if request.method == 'POST': form = CustomerDepositForm(request.POST) if form.is_valid(): amount = form.cleaned_data['deposit_amount'] # 创建存款记录 Deposit.objects.create( customer=customer, acct=acct, staff=user, deposit_amount=amount ) messages.success(request, f'N{amount} Credited for Account {acct} Successfully.') return redirect('deposit-slip') else: # 表单验证失败,返回存款页面提示错误 messages.error(request, '存款金额无效,请重新输入') return redirect('create-deposit', id=id) else: # GET请求直接跳转到存款表单页面 return redirect('create-deposit', id=id)
3. 优化customer_deposit视图逻辑
简化日期和月份获取方式,明确处理表单验证失败场景:
from django.utils import timezone from django.db.models import Sum, DecimalField from django.shortcuts import render, redirect, get_object_or_404 from django.contrib import messages from .models import Deposit, Customer from .forms import CustomerDepositForm def customer_deposit(request, id): page_title = "Customer Deposit" current_date = timezone.now().date() current_month_name = timezone.now().strftime('%B') # 简化月份名称获取 customer = get_object_or_404(Customer, id=id) acct = customer.account_number # 获取客户总存款,默认值为0.00 total_deposit = Deposit.objects.filter(customer=customer).aggregate( total=Sum('deposit_amount', output_field=DecimalField()) )['total'] or Decimal('0.00') if request.method == 'POST': form = CustomerDepositForm(request.POST) if form.is_valid(): amount = form.cleaned_data['deposit_amount'] context = { 'deposit': total_deposit, 'page_title': page_title, 'customer': customer, 'current_date': current_date, 'current_month_name': current_month_name, 'amount': amount, 'acct': acct, } return render(request, 'dashboard/deposit_approval_form.html', context) else: # 表单验证失败,返回带错误的存款页面 context = { 'deposit': total_deposit, 'page_title': page_title, 'customer': customer, 'current_date': current_date, 'current_month_name': current_month_name, 'form': form, 'acct': acct, } return render(request, 'dashboard/deposit.html', context) else: form = CustomerDepositForm() context = { 'deposit': total_deposit, 'page_title': page_title, 'customer': customer, 'current_date': current_date, 'current_month_name': current_month_name, 'form': form, 'acct': acct, } return render(request, 'dashboard/deposit.html', context)
内容的提问来源于stack exchange,提问作者apollos
相关产品推荐
相关产品推荐

