Django表单处理:创建Transaction并关联为AccountBooking外键报错
问题描述
处理ModelForm时,希望不让用户填写fk_transaction字段,后台自动创建一条Transaction记录并关联到AccountBooking。表单显示正常,Transaction能创建,但视图中尝试将记录添加到表单保存时,提示该字段不存在。
代码片段
views.py
from django.http import HttpResponse from django.shortcuts import render from forms import AccountBookingForm from models import Transaction def deposit(request): context = {} if request.method == "POST": form = AccountBookingForm(request.POST) t = Transaction() form.fk_transaction = t form.save() return render(request, "deposit_success.html", {"form": form}) else: form = AccountBookingForm() return render(request, "deposit.html", {"form": form})
models.py
class Transaction(models.Model): type = models.CharField(max_length=11, choices=TR_TYPE_CHOICES, default=DEPOSIT) status = models.CharField(max_length=11, choices=TR_STATUS_CHOICES, default=DRAFT) text = models.TextField(max_length=500, default="", blank=True) class AccountBooking(models.Model): fk_bankaccount = models.ForeignKey( BankAccount, on_delete=models.CASCADE, blank=False) fk_transaction = models.ForeignKey(Transaction, on_delete=models.CASCADE, blank=False) value = models.DecimalField(max_digits=14, decimal_places=2, blank=False)
forms.py
from django.forms import ModelForm from .models import AccountBooking class AccountBookingForm(ModelForm): class Meta: model = AccountBooking fields = ["__all__"] exclude = ("fk_transaction",)
解决方案
问题出在直接给form对象赋值fk_transaction——因为你已经在表单中排除了这个字段,form实例上不存在该属性。正确操作步骤:
- 先保存Transaction记录(外键必须关联已存在的数据库记录)
- 使用
form.save(commit=False)获取未写入数据库的AccountBooking实例 - 给该实例补充
fk_transaction字段后再保存
修改后的views.py代码:
from django.http import HttpResponse from django.shortcuts import render from forms import AccountBookingForm from models import Transaction def deposit(request): context = {} if request.method == "POST": form = AccountBookingForm(request.POST) if form.is_valid(): # 必须先验证表单数据合法性 t = Transaction.objects.create() # 创建并保存Transaction到数据库 booking = form.save(commit=False) # 获取未保存的AccountBooking实例 booking.fk_transaction = t booking.save() # 最终保存AccountBooking记录 return render(request, "deposit_success.html", {"form": form}) else: form = AccountBookingForm() return render(request, "deposit.html", {"form": form})
补充说明:
- 务必调用
form.is_valid(),避免因非法数据导致后续保存失败 Transaction.objects.create()等价于创建实例后调用save(),写法更简洁commit=False会生成模型实例但不写入数据库,方便补充表单未包含的字段
内容的提问来源于stack exchange,提问作者Dennis
相关产品推荐
相关产品推荐

