如何在Django表单中加载数据库初始数据供用户更新?
问题:从数据库加载数据到表单时获取到DeferredAttribute而非实际值
我需要从数据库加载数据到表单供用户更新,但当前方法得到的是<django.db.models.query_utils.DeferredAttribute object at 0x000001DB8861EAC0>而非货币值,请问如何在init_supplier字典中放入正确的数据?已尝试在表单中使用__init__方法以及在视图中进行过滤。
相关代码
views.py代码
def supplier_form(request): s_data = supplier.objects.all init_supplier = { 'currency' : supplier.currency } submitted = False if request.method == "POST": form = s_form(request.POST) if form.is_valid(): form.save() return HttpResponseRedirect('/home?submitted=TRUE') else: sup_form = s_form(initial=init_supplier) if submitted in request.GET: submitted = True return render(request, 'forms/supplier_form.html', {'sup_form':sup_form, 'submitted':submitted, 's_data' : s_data})
models.py代码
class Supplier(models.Model): company_name = models.OneToOneField(User, max_length=120, on_delete=models.DO_NOTHING) currency = models.CharField('Currency', max_length=4) legal_form = models.CharField('Legal form', max_length=100, choices=legal_form_options, default='Sole proprietorship') accounting_standards = models.CharField('Accounting standards', max_length=100) owner_structure = models.CharField('Owner structure', max_length=100) industry_sector = models.CharField('Industry sector', max_length=100, choices=industry_sector_options, default='Advertising')
解决方案
你当前的问题是直接引用了supplier.currency——这是模型类的字段属性,不是具体实例的数值,所以得到的是DeferredAttribute对象。要解决这个问题,核心是获取具体的Supplier实例,再提取它的currency值。
步骤1:获取目标Supplier实例
因为你的Supplier和User是一对一关系,通常是加载当前登录用户对应的Supplier数据:
try: # 通过当前登录用户关联获取Supplier实例 supplier_instance = Supplier.objects.get(company_name=request.user) except Supplier.DoesNotExist: # 处理用户没有对应Supplier的情况,比如跳转到创建页面 return HttpResponseRedirect('/create-supplier')
步骤2:用实例数据填充init_supplier
init_supplier = { 'currency': supplier_instance.currency }
修正后的完整views.py代码
def supplier_form(request): # 先校验用户是否登录 if not request.user.is_authenticated: return HttpResponseRedirect('/login') # 获取当前用户对应的Supplier实例 try: supplier_instance = Supplier.objects.get(company_name=request.user) except Supplier.DoesNotExist: return HttpResponseRedirect('/create-supplier') init_supplier = { 'currency': supplier_instance.currency } submitted = False if request.method == "POST": # 绑定实例到表单,提交时会直接更新该实例而非创建新数据 form = s_form(request.POST, instance=supplier_instance) if form.is_valid(): form.save() return HttpResponseRedirect('/home?submitted=TRUE') else: # 传入instance参数后,表单会自动加载实例的所有字段数据,initial可以省略 sup_form = s_form(instance=supplier_instance) if 'submitted' in request.GET: submitted = True # 修正原代码的语法错误:objects.all需要加括号 s_data = Supplier.objects.all() return render(request, 'forms/supplier_form.html', {'sup_form':sup_form, 'submitted':submitted, 's_data' : s_data})
额外提示
- 模型类名遵循Python规范应该用大驼峰
Supplier,你原代码里的小写supplier容易混淆类和实例,建议统一修正。 - 表单更新时直接传入
instance参数是更简洁的方式,不需要手动编写initial字典,表单会自动加载实例的所有字段值。
内容的提问来源于stack exchange,提问作者Piotr Połetek
相关产品推荐
相关产品推荐

