Hi,
I'm using an inlineformset to present an object with all values read-only. can_delete is set to True and not read-only. The user should only be able to delete objects, but not change a value.
This is the code parts that I use:
view:
PMWPDRFormSet = inlineformset_factory(ProjectMembership, PMSWorkPlaceDayRate, form=ProjectMembershipWorkPlaceDayRateUpdateForm, max_num=10, extra=0, can_delete=True)
Form:
class ProjectMembershipWorkPlaceDayRateUpdateForm(forms.ModelForm):
project_membership = forms.ModelChoiceField(ProjectMembership.objects, widget=HiddenInput())
work_place = forms.ModelChoiceField(ProjectWorkPlace.objects)
day_rate = forms.IntegerField(required=False)
class Meta:
model = PMSWorkPlaceDayRate
Model:
class PMSWorkPlaceDayRate(models.Model):
project_membership = models.ForeignKey(ProjectMembership)
work_place = models.ForeignKey(ProjectWorkPlace)
day_rate = models.PositiveIntegerField(max_length=11)
created_by = models.ForeignKey(User, editable=False, related_name='project_membership_work_place_day_rate_creator')
created = models.DateTimeField(auto_now_add=True, editable=False, verbose_name='creation date')
modified_by = models.ForeignKey(User, editable=False, related_name='project_membership_work_place_day_rate_modifier')
modified = models.DateTimeField(auto_now=True, editable=False)
class Meta:
unique_together = (("project_membership", "work_place"),)
Routine to make the form without the delete checkbox read-only:
for form in form_set.forms:
for name, field in form.fields.items():
if name != "DELETE":
field.widget.attrs['readonly'] = True
field.widget.attrs['disabled'] = True
return form_set
Now I want to achieve in the view that if the user selected the delete checkbox that the object is deleted. I do it like this:
pmwpdr_form_set = PMWPDRFormSet(request.POST, request.FILES, instance=project_membership)
if pmwpdr_form_set.is_valid():
for form in pmwpdr_form_set.forms:
try:
if form.cleaned_data:
if form.cleaned_data["DELETE"]:
pmwpdr_id = form.cleaned_data["id"]
pmwpdr =PMSWorkPlaceDayRate.objects.get(pk=pmwpdr_id.pk)
pmwpdr.delete()
#delete the corresponding ProjectMembershipWorkPlaceDayRate object
request.user.message_set.create(message='The Work Place Day Rate %s was deleted successfully".' % (pmwpdr_id))
(pmwpdr.project_membership.__str__()))
except AttributeError:
pass
if not pmwpdr_form_set.forms:
request.user.message_set.create(message='You provided no data. Nothing has changed.')
return HttpResponseRedirect(reverse('show_pmwpdr', args=(project_membership.id,)))
When I execute this code I get the following error:
MultiValueDictKeyError at /pm/projects/memberships/18/show_pmwdpr/
"Key 'pmsworkplacedayrate_set-0-id' not found in <QueryDict: {u'pmsworkplacedayrate_set-TOTAL_FORMS': [u'1'], u'pmsworkplacedayrate_set-INITIAL_FORMS': [u'1']}>"
The error is raised in the following line of code:
if request.method == 'POST':
pmwpdr_form_set = PMWPDRFormSet(request.POST, request.FILES, instance=project_membership)
This is probably since the values are not transfered when an input field is disabled. But the interesting thing is that if I leave the day_rate field enabled it works. I would expect also an error for the still disabled work_place field.
That leads me to the assumption that something else is wrong and it might work the way that I tried it.
To bring this down to an answer: Why does my code not work and what would be a way to use inlineformset_factory with disabled fields and even so being able to delete an object!?