Django中关联用户的Parceiros对象创建失败,POST请求返回302
解决Parceiros对象创建失败(返回302但未生成对象)的问题
看起来你遇到的核心问题是表单初始化和OneToOne关系的处理不当,导致要么抛出未捕获的异常,要么误以为是创建新对象但实际是更新现有对象。让我们一步步分析并修复:
1. 主要问题分析
表单实例传递错误(GET请求)
在你的视图parceiros_create的GET分支中,你传递了instance=request.user给ParceirosForm——但这个表单是基于Parceiros模型的,必须接收Parceiros实例作为instance参数,而不是User实例。这会导致表单初始化异常,无法正确准备创建新对象的表单。
POST请求未处理无关联Parceiros的情况
当用户还没有关联的Parceiros对象时,直接访问request.user.parceiros会抛出Parceiros.DoesNotExist异常(因为OneToOne关系要求每个用户最多有一个关联对象)。如果没有捕获这个异常,请求会直接失败,但你提到有成功提示,可能是你已经创建过Parceiros对象,此时form.save()只是更新现有对象,而非创建新对象。
其他次要问题
- 表单中
endereco字段使用TextInput控件,与模型的TextField不匹配(应该用Textarea渲染多行输入); - 模型中
created_at和updated_at的参数写反了(auto_now_add用于创建时间,auto_now用于更新时间)。
2. 修复方案
修复视图函数(views.py)
我们需要先检查用户是否已有Parceiros对象,没有的话创建一个未保存的实例关联到当前用户,确保表单初始化正确:
from django.contrib.auth.decorators import login_required from django.db import transaction from django.shortcuts import render, redirect from django.contrib import messages from .forms import ParceirosForm from .models import Parceiros @login_required @transaction.atomic def parceiros_create(request): try: # 尝试获取用户已有的Parceiros对象 parceiro_instance = request.user.parceiros except Parceiros.DoesNotExist: # 若没有,创建一个未保存的实例并关联当前用户 parceiro_instance = Parceiros(user=request.user) if request.method == 'POST': form = ParceirosForm(request.POST, instance=parceiro_instance) if form.is_valid(): form.save() messages.success(request, ('Parceiro criado')) return redirect('home2') else: messages.error(request, ('Please correct the error below.')) else: form = ParceirosForm(instance=parceiro_instance) context = { 'form': form, } return render(request, 'parceiroform.html', context)
修复表单(forms.py)
将endereco字段的控件改为Textarea,匹配模型的TextField:
from django import forms from phonenumber_field.formfields import PhoneField from .models import Parceiros class ParceirosForm(forms.ModelForm): nome = forms.CharField(max_length=200) endereco = forms.CharField(widget=forms.Textarea) # 替换TextInput为Textarea responsavel = forms.CharField(max_length=100) tel = PhoneField(max_length=12) class Meta: prefix = 'parceiro' model = Parceiros fields = ['nome', 'endereco', 'responsavel', 'tel']
修复模型时间字段(models.py)
纠正created_at和updated_at的参数:
from django.db import models from django.contrib.auth import get_user_model from phonenumber_field.modelfields import PhoneField User = get_user_model() class Parceiros(models.Model): user = models.OneToOneField(User, on_delete=models.CASCADE) nome = models.CharField(max_length=200) endereco = models.TextField(max_length=400, blank=True) responsavel = models.CharField(max_length=100) tel = PhoneField(max_length=12) created_at = models.DateTimeField(auto_now_add=True) # 仅创建时设置 updated_at = models.DateTimeField(auto_now=True) # 每次保存时更新 ativo = models.BooleanField(default=False) def __str__(self): return '%s %s' % (self.user, self.nome)
3. 为什么之前会出现问题?
- 302状态码是正常的:因为表单验证通过后你执行了
redirect('home2'),重定向的状态码就是302,这不是错误; - 未创建对象的原因:要么是你已经有了关联的
Parceiros对象(OneToOne关系只能有一个,此时form.save()是更新),要么是表单初始化错误导致保存失败但未抛出可见异常。
内容的提问来源于stack exchange,提问作者lucasrf27
相关产品推荐
相关产品推荐

