Reputation: 4664
I have a many-to-many field and in order to save the retrieved data from the form, initially, I have to save an instance of that table, otherwise, I get an error like:
"Order: None" needs to have a value for field "id" before this many-to-many relationship can be used.
But the issue is when I have 2 save methods called, they also create 2 different logs(at the first save()
it creates the instance and at the letter one it edits it) and this cause the chaos. Therefore, I want to be able to commit=False
in the first one and finalize the save in the second save()
. Commit is used for ModalForm
, however, my form extends form.Forms
.
if request.method == 'POST':
form = OrderAddForm(request.POST)
if form.is_valid():
order = Order()
order.user = request.user
order.save()
order.ordered_materials.set(form.cleaned_data['ordered_materials'])
order.location = form.cleaned_data['location']
order.note = form.cleaned_data['note']
form.save()
else:
form = OrderAddForm()
class OrderAddForm(forms.Form):
ordered_materials = forms.ModelMultipleChoiceField(
queryset=Material.objects.all(),
)
location = forms.CharField()
note = forms.CharField()
ordered_materials.widget.attrs.update({'id': 'materialsid',
'class': 'form-control',
})
class Order(models.Model):
user = models.ForeignKey(User,
on_delete=models.CASCADE)
ordered_materials = models.ManyToManyField('Material')
location = models.CharField(max_length=500)
note = models.CharField(max_length=30,
verbose_name="Note")
STATUS = (
('n', 'None'),
('a', 'Accepted'),
('r', 'Rejected'),
)
status_name = models.CharField(max_length=1,
choices=STATUS,
default='n')
def __str__(self):
return str(self.id)
Upvotes: 0
Views: 2096
Reputation: 308789
You don't have to save the object after setting the many-to-many field. Therefore you should be able to re-arrange your code so that you only call save()
once.
if form.is_valid():
order = Order()
order.user = request.user
order.location = form.cleaned_data['location']
order.note = form.cleaned_data['note']
order.save()
order.ordered_materials.set(form.cleaned_data['ordered_materials'])
Upvotes: 3