I have four fields in a model, one of which is a foreign key field and the other three are m2m fields. The form is opened in the modal, but the data is not being saved, Error given below. I don't understand what I did wrong. I would be very grateful for a little help.
Model:
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
Form:
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']
Template:
{% 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>
View:
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);
error:
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.
class Meta:
model = ProductSize
fields = ['product','size','colour','cupsize']
Here, the model should be
model = ProductAttributes
Since the model you specified here ProductSize
does exist, submitting form will just create another instance to ProductSize
model without those specific fields and error messages. You can check your admin page.
EDIT ******
2. Based on what you added in the question and the error message, it looks like in attribute_create
you are passing product's pk. Now in the attribute_create
, you are passing initial dict {'product': pk}
. This is wrong, because, in your ProductAttributesForm
, the product
field should be an instance rather than a pk
.
You need to refer product as
product = Product.objects.filter(pk=pk)
initial = {'product':product}
The current error message will be gone, but you will have other errors.