I have a problem saving many to many fields from a form. Here are my models:
class TextIssue(models.Model):
Issue = models.CharField(max_length=150, unique=True)
def __unicode__(self):
return self.Issue
class PadIssue(models.Model):
Issue = models.CharField(max_length=150, unique=True)
def __unicode__(self):
return self.Issue
class PHIssue(models.Model):
Data = models.ForeignKey(Data)
TextIssue = models.ManyToManyField(TextIssue, blank=True, null=True)
PadIssue = models.ManyToManyField(PadIssue, blank=True, null=True)
Notes = models.TextField()
def clean(self):
from django.core.exceptions import ValidationError
if self.TextIssue is None and self.PadIssue is None:
raise ValidationError('You must choose at least one issue category.')
if self.Notes is None:
raise ValidationError('You must write a note regarding the issues selected above.')
class PHIssueForm(ModelForm):
class Meta:
model = PHIssue
exclude = ('Data',)
And here I process the post request in my views.py:
def process_npiform(request, npi_id=None):
if npi_id:
try:
npi = Data.objects.get(id=int(npi_id))
except:
raise Http404
if request.method == 'POST':
data = DataForm(request.POST, instance=npi, prefix='npi_data')
if data.is_valid():
update = data.save(commit=False)
if not request.user.is_superuser:
update.User = request.user
update.save()
if update.Status == 'past-due':
try:
prefab = PHIssue.objects.get(Data=npi)
except:
prefab = PHIssue(Data=Data.objects.get(id=int(update.id)))
prefab.save()
issue = PHIssueForm(request.POST, instance=prefab, prefix='npi_issue')
if issue.is_valid():
save_issue = issue.save(commit=False)
save_issue.save()
return HttpResponseRedirect(reverse('pm'))
else:
return render_to_response('npi/data.html', {'data': data, 'issue': issue}, context_instance=RequestContext(request))
else:
return HttpResponseRedirect(reverse('pm'))
Whenever I save through the form, only the Notes text field gets saved in the PHIssue instance, and the many to many fields are left blank. Can someone help me find what is wrong?
In a nutshell: Make a form for each model, submit them both to template in a single <form> , using prefix keyarg and have the view handle validation. If there is dependency, just make sure you save the "parent" model before dependant, and use parent's ID for foreign key before commiting save of "child" model.
Django Model Form It is a class which is used to create an HTML form by using the Model. It is an efficient way to create a form without writing HTML code. Django automatically does it for us to reduce the application development time.
To work around this problem, every time you save a form using commit=False, Django adds a save_m2m() method to your ModelForm subclass. After you've manually saved the instance produced by the form, you can invoke save_m2m() to save the many-to-many form data.
create() will automatically save, so even if you fix your error - you will still have to make sure the arguments to create fulfill the database requirements to save a record.
http://docs.djangoproject.com/en/dev/topics/forms/modelforms/#the-save-method
When using commit=False
, you have to call save_m2m()
m2m relationships require the parent object to be saved first, which you are not doing by using commit=False
You can do like this for example:
if todo_list_form.is_valid():
todo_list = todo_list_form.save(commit=False)
todo_list.save()
todo_list_form.save_m2m()
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With