【问题标题】:ValueError: Cannot assign value: must be an instanceValueError:无法赋值:必须是实例
【发布时间】:2021-03-10 22:38:50
【问题描述】:

我在一个模型中有四个字段,其中一个是外键字段,另外三个是 m2m 字段。表单在模态中打开,但未保存数据,错误如下。我不明白我做错了什么。如果能提供一点帮助,我将不胜感激。

型号:

class ProductAttributes(models.Model):
    product     = models.ForeignKey('Product', blank=True, null=True, on_delete=models.SET_NULL)
    size        = models.ManyToManyField('ProductSize', blank=True)
    colour      = models.ManyToManyField('ProductColour', blank=True)
    cupsize     = models.ManyToManyField('ProductCupSize', blank=True)

    def __str__(self):
        return self.product

表格:

class ProductAttributesForm(forms.ModelForm):
    product     = forms.IntegerField(label=('ID'),required=True, disabled=True)
    size        = forms.ModelMultipleChoiceField(queryset=ProductSize.objects.all(),widget=Select2MultipleWidget, required=False)
    colour      = forms.ModelMultipleChoiceField(queryset=ProductColour.objects.all(),widget=Select2MultipleWidget, required=False)
    cupsize     = forms.ModelMultipleChoiceField(queryset=ProductCupSize.objects.all(),widget=Select2MultipleWidget, required=False)

    class Meta:
        model = ProductAttributes
        fields = ['product','size','colour','cupsize']

模板:

{% load crispy_forms_tags %}

<form id="Form" method="post" action="{% url 'accpack:products_attributes_create' product %}" class="js-product-create-form col s12" >
    {% csrf_token %}
    {% crispy form form.helper %}
</form>

查看:

def save_attribute_form(request, form, template_name, pk):
    data = dict()
    if request.method == 'POST':
        if form.is_valid():
            form.save()
            data['form_is_valid'] = True
        else:
            data['form_is_valid'] = False
    context = {'form': form, 'product':pk}
    data['html_form'] = render_to_string(template_name, context, request=request)
    return JsonResponse(data)

def attribute_create(request, pk):
    if request.method == 'POST':
        form = ProductAttributesForm(request.POST, initial={'product': pk})
    else:
        form = ProductAttributesForm(initial={'product': pk})
    return save_attribute_form(request, form, 'main/products/partial_product_attribute_form.html', pk)

ajax:

 var saveForm = function () {
    var form = $(this);
    $.ajax({
      url: form.attr("action"),
      data: form.serialize(),
      type: form.attr("method"),
      dataType: 'json',
      success: function (data) {
        if (data.form_is_valid) {
          $("#modal-product_attribute").modal("hide");
          console.log(data.form_data);
        }
        else {
          $("#modal-product_attribute .modal-content").html(data.html_form);
        }
      }
    });
    return false;
  $("#modal-product_attribute").on("submit", ".js-product-create-form", saveForm);

错误:

File "C:\ProgramData\Anaconda3\envs\djangoproject\lib\site-packages\django\db\models\fields\related_descriptors.py", line 220, in __set__
    self.field.remote_field.model._meta.object_name,
ValueError: Cannot assign "111": "ProductAttributes.product" must be a "Product" instance.

【问题讨论】:

    标签: django ajax m2m


    【解决方案1】:
    1. 您的 forms.py 中有错误。
        class Meta:
            model = ProductSize
            fields = ['product','size','colour','cupsize']
    

    这里的模型应该是

          model = ProductAttributes
    

    由于您在此处指定的模型ProductSize 确实存在,因此提交表单只会为ProductSize 模型创建另一个实例,而没有这些特定字段和错误消息。您可以查看您的管理页面。

    编辑****** 2.根据您在问题中添加的内容和错误消息,在attribute_create 中您正在传递产品的pk。现在在attribute_create 中,您正在传递初始字典{'product': pk}。这是错误的,因为在您的ProductAttributesForm 中,product 字段应该是一个实例而不是pk

    您需要将产品称为

    product = Product.objects.filter(pk=pk)
    initial = {'product':product}
    

    当前的错误信息将消失,但您会遇到其他错误。

    【讨论】:

    • 我错过了一件严肃的事情,谢谢。表格现在没有提交。收到错误the server responded with a status of 500 (Internal Server Error)
    • 很高兴它解决了您的问题。我希望 django 可以针对这种情况给出警告信息,例如,未找到字段。当没有错误信息时,很难找到解决方案。
    • 我刚刚编辑了我的评论,请看一下。
    • 您是否尝试通过 ajax 提交表单? 500 错误通常与 ajax 有关。你有ajax代码吗?
    • self.field.remote_field.model._meta.object_name, ValueError: Cannot assign "111": "ProductAttributes.product" must be a "Product" instance.