【问题标题】:Django formview returns object already exists error with a modelformDjango formview返回对象已存在模型表单错误
【发布时间】:2026-01-24 17:10:01
【问题描述】:

我正在尝试创建一个接收字符串的 FormView,但是当我完成我提供的字段时,它给了我一个“对象已存在”错误。我要做的是创建一个视图来检查某个“产品”(模型)是否存在,如果该产品确实存在,则基于产品“pk”重定向到另一个视图以创建另一个模型。

基本上操作过程是这样的:

  • 检查产品是否存在。
  • 如果存在重定向创建订单(模型)视图,否则什么都没有。
  • 填写创建订单表单,如果有效,创建订单并将产品fk关系分配给订单。

这是我的代码

views.py

class BuyOrderCheckProduct(generic.FormView):
    template_name = 'buy_order/buy_order_check_product.html'
    form_class = forms.CheckProductForm

    def form_valid(self, form):
        try:
            product = Product.objects.get(codename=form.cleaned_data['codename'])
        except Product.DoesNotExist:
            product = None
        if product:
            # Never enters here because correct existing codename gives form_invalid, don't know why
            return super(BuyOrderCheckProduct, self).form_valid()
        else:
            # It only enters when I input a non-existent codename for product
            return super(BuyOrderCheckProduct, self).form_invalid()

    def form_invalid(self, form):
        # I don't know why it enters here!
        return super(BuyOrderCheckProduct, self).form_invalid()  

    def get_success_url(self, **kwargs):
        # TODO: How to pass product pk as kwargs?
        return reverse_lazy('order_create', self.kwargs['pk'])

class BuyOrderCreate(generic.CreateView):
    template_name = 'buy_order/buy_order_create.html'
    form_class = forms.BuyOrderCreateForm
    success_url = reverse_lazy('buy_order_list')
    # TODO: Need to create a custom form_valid to add product fk to order.

forms.py

class CheckProductForm(forms.ModelForm):
    class Meta:
        model = Product
        fields = ['codename']

class BuyOrderCreateForm(forms.ModelForm):
    class Meta:
        model = BuyOrder

models.py

"""
ORDER
"""
class Order(models.Model):
    class Meta:
        verbose_name = u'orden'
        verbose_name_plural = u'ordenes'
        abstract = True

    unit_price = models.IntegerField(u"precio unitario", )
    quantity = models.IntegerField(u"cantidad", default=1)
    discount = models.IntegerField(u"descuento")

    def __unicode__(self):
        return self.code

class BuyOrder(Order):
    class Meta:
        verbose_name = u'orden de compra'
        verbose_name_plural = u'ordenes de compra'

    product = models.ForeignKey(Product, related_name="buy_orders", editable = False)
    bill = models.ForeignKey(BuyBill, related_name="orders", null=True, editable = False)

"""
PRODUCT
"""
class Product(models.Model):
    class Meta:
        verbose_name = u'producto'
        verbose_name_plural = u'productos'

    category        = models.ForeignKey(Category, verbose_name=u'categoría', related_name='products')
    codename        = models.CharField(u"código", max_length=100, unique=True)
    name            = models.CharField(u"nombre", max_length=100)
    description     = models.TextField(u"descripción", max_length=140, blank=True)
    sale_price      = models.IntegerField(u"precio de venta", default=0)
    purchase_price  = models.IntegerField(u"precio de compra", default=0)
    profit          = models.IntegerField(u"lucro", default=0)
    profit_margin   = models.IntegerField(u"margen de lucro", default=0)
    tax             = models.IntegerField(u"tasa", default=0)
    quantity        = models.IntegerField(u"cantidad", default=0)
    picture         = models.ImageField(u"imagen", upload_to='product_pictures', blank=True)
    group           = models.ForeignKey(Group, verbose_name=u'grupo', related_name='products')

    def __unicode__(self):
        return self.name

如果您能给我一个提示,为这种情况创建正确的 get_success_url(),我将不胜感激。

【问题讨论】:

  • 你能粘贴错误吗?
  • 您在 form_valid 中为 form_invalid 使用 super() 覆盖。为什么不根据对象是否存在进行重定向?
  • 它在表单上返回“具有此代号的产品已存在”错误。

标签: django django-forms django-views


【解决方案1】:

好的。我找到了解决我的错误的方法。导致model already exists 错误的是我的ModelForm CheckProductForm。 Codename 属性是唯一的,所以我的验证总是返回 False。我所做的是将原来的 ModelForm 更改为 Form。这解决了我的整个问题。对于 form_valid 中的 form_invalid 问题。如果产品不存在,我已经覆盖了表单的 clean_codename 函数以引发 ValidationError。

这是我找到的解决方案:

views.py

class BuyOrderCheckProduct(generic.FormView):
    template_name = 'buy_order/buy_order_check_product.html'
    form_class = forms.CheckProductForm

    def form_valid(self, form):
        product = Product.objects.get(codename=form.cleaned_data['codename'])
        return redirect('buy_order_create', pk=product.pk)

forms.py

class CheckProductForm(forms.Form):
    codename = forms.CharField(label=u'código')

    def clean_codename(self):
        try:
            product = Product.objects.get(codename=self.cleaned_data['codename'])
        except Product.DoesNotExist:
            raise forms.ValidationError("This codename doesn't exist.")
        return product

PD:很抱歉这些愚蠢的问题。

【讨论】: