Hi,
I have a model called Party. Each party can have multiple ratings from different rating sources. These ratings use a model called PartyRating. PartyRating has four foreign keys to link the PartyRating to a party, a rating source, a rating and an outlook. I’d like to manage the party ratings on the edit page for the party, so I am using inline forests for the PartyRating. When the edit page loads, the formset loads the ratings without issue. However, when saving the PartyRating, I am struggling to get the POST data into the inline formset for validation and saving.
Although I can see the values from the inline formset in the POST data, the inline formset object does not look to be populating and the subsequent is_valid() method fails, though I am not able to produce a failure message from that.
Models.py
class Party(models.Model):
name = models.CharField(_('Name'), max_length=200, db_comment='Party Name', help_text='Party Name')
external_comment = models.CharField("External Comment", max_length=1000, blank=True)
internal_comment = models.CharField("Internal Comment", max_length=1000, blank=True)
...
class PartyRating(models.Model):
party = models.ForeignKey('Party', on_delete=models.PROTECT)
rating = models.ForeignKey('Rating', on_delete=models.PROTECT)
rating_source = models.ForeignKey('RatingSource', on_delete=models.PROTECT)
outlook = models.ForeignKey('Outlook', on_delete=models.PROTECT, null=True)
created = models.DateTimeField(_('Created'), auto_now_add=True)
created_by = models.ForeignKey('Person', on_delete=models.PROTECT, related_name='party_rating_created_by', verbose_name=_('Created By'))
modified = models.DateTimeField(_('Modified'), auto_now=True)
modified_by = models.ForeignKey('Person', on_delete=models.PROTECT, related_name='party_rating_modified_by', verbose_name=_('Modified By'))
modified_from = models.CharField(_('Modified From'), max_length=200)
class Meta:
unique_together = ('party', 'rating_source',)
Views.py
def partyUpdate(request, partyId):
party = Party.objects.get(pk=partyId)
party_form = PartyForm(instance=party)
party_rating_formset = PartyRatingInlineFormSet(instance=party)
if request.method == "POST":
party_form = PartyForm(request.POST, instance=party)
if party_form.is_valid():
party_form = get_update_form_defaults(party_form)
party_form.save()
party_rating_formset = PartyRatingInlineFormSet(data=request.POST, instance=party)
if party_rating_formset.is_valid():
for form in party_rating_formset:
form.save()
return HttpResponseRedirect(reverse(get_update_url(Party), args=[party.id]))
else:
context = { 'party_form': party_form, 'party_rating_formset': party_rating_formset,}
context = get_update_context_additions(context, Party, party)
return render(request, 'core/party_form.html', context)
Forms
class PartyForm(forms.ModelForm):
class Meta:
model = Party
fields = "__all__"
exclude = get_form_exclude_default()
widgets = {
'last_credit_assessment': DateInput(),
}
class PartyRatingForm(forms.ModelForm):
class Meta:
model = PartyRating
fields = "__all__"
exclude = get_form_exclude_default()
PartyRatingInlineFormSet = inlineformset_factory(Party, PartyRating, fields=('rating_source','rating','outlook',), form=PartyRatingForm, extra=1, can_delete=True)
Template
<form method="post">{% csrf_token %}
{{ form.errors }}
{{ form.non_field_errors }}
<table>
{% for field in party_form %}
<tr><td>{{ field.label_tag }}</td><td>{{ field }}</td></tr>
{% endfor %}
</table><br>
<table>
<tr>
{% for field in party_rating_formset.form %}
<th>{{ field.label_tag }}</th>
{% endfor %}
</tr>
{% for form in party_rating_formset %}
<tr>
{% for field in form %}
<td>{{ field }}</td>
{% endfor %}
</tr>
{% endfor %}
</table><br>
<input type="submit" value="Submit">
</form>