Django含多对多关系表单无法保存问题求助
问题分析与解决方案
报错'VoucherForm' object has no attribute 'user'的核心原因是你试图操作表单对象的多对多字段,而多对多字段属于Voucher模型实例,不是表单实例。另外代码还有几处逻辑错误,逐一修正如下:
关键错误点
- 多对多字段操作对象错误:
voucherform.user.add(...)写法错误,必须用保存后的Voucher实例(而非表单对象)来添加关联。 - 多对多关联对象类型错误:
Voucher.user关联的是User模型,不是UserProfile,需要传入userprofile.user而非userprofile本身。 venue查询逻辑错误:values('venue')返回的是QuerySet字典,不能直接赋值给venue_id,应该直接获取Venue对象。- GET请求中表单实例化错误:
voucherform = VoucherForm是引用类,不是创建实例,必须写成voucherform = VoucherForm()。
修正后的视图代码
def add_voucher(request, userprofile_id): url = request.META.get('HTTP_REFERER') # 直接获取当前用户关联的Venue对象 current_user_profile = UserProfile.objects.get(user=request.user) venue = current_user_profile.venue target_userprofile = UserProfile.objects.get(id=userprofile_id) submitted = False if request.method == "POST": voucherform = VoucherForm(request.POST) if voucherform.is_valid(): # 保存但暂不提交到数据库 voucher = voucherform.save(commit=False) # 外键直接赋值对象 voucher.venue = venue voucher.save() # 给多对多字段添加关联的User对象 voucher.user.add(target_userprofile.user) return HttpResponseRedirect(url) else: # 正确实例化表单 voucherform = VoucherForm() if 'submitted' in request.GET: submitted = True # 修正redirect参数传递方式 return redirect('venue-loyalty-card', submitted=submitted, userprofile=target_userprofile)
额外说明
- 因为表单未包含
user多对多字段,所以不需要调用voucherform.save_m2m(),该方法仅用于保存表单中声明的多对多字段数据。 - 原代码中
data.user_id = userprofile.id完全无效,多对多字段无法通过直接赋值_id关联,必须使用add()方法。
内容的提问来源于stack exchange,提问作者PhilM
相关产品推荐
相关产品推荐

