The setup =
I have this class, Transcript:
class Transcript(models.Model):
body = models.TextField('Body')
doPagination = models.BooleanField('Paginate')
numPages = models.PositiveIntegerField('Number of Pages')
and this class, TranscriptPages(models.Model):
class TranscriptPages(models.Model):
transcript = models.ForeignKey(Transcript)
order = models.PositiveIntegerField('Order')
content = models.TextField('Page Content', null=True, blank=True)
The Admin behavior I’m trying to create is to let a user populate Transcript.body with the entire contents of a long document and, if they set Transcript.doPagination = True and save the Transcript admin, I will automatically split the body into n Transcript pages.
In the admin, TranscriptPages is a StackedInline of the Transcript Admin.
To do this I’m overridding Transcript’s save method:
def save(self):
if self.doPagination:
#do stuff
super(Transcript, self).save()
else:
super(Transcript, self).save()
The problem =
When Transcript.doPagination is True, I want to manually delete all of the TranscriptPages that reference this Transcript so I can then create them again from scratch.
So, I thought this would work:
#do stuff
TranscriptPages.objects.filter(transcript__id=self.id).delete()
super(Transcript, self).save()
but when I try I get this error:
Exception Type: ValidationError
Exception Value: [u’Select a valid
choice. That choice is not one of the
available choices.’]
… and this is the last thing in the stack trace before the exception is raised:
…/django/forms/models.py in save_existing_objects
- pk_value = form.fields[pk_name].clean(raw_pk_value)
Other attempts to fix:
- t =
self.transcriptpages_set.all().delete()
(where self = Transcript from the
save() method) - looping over t (above) and deleting each item individually
- making a post_save signal on TranscriptPages that calls the delete method
Any ideas? How does the Admin do it?
UPDATE: Every once in a while as I’m playing around with the code I can get a different error (below), but then it just goes away and I can’t replicate it again… until the next random time.
Exception Type:
MultiValueDictKeyError Exception
Value: “Key ‘transcriptpages_set-0-id’
not found in ”
Exception Location:
…/django/utils/datastructures.py in
getitem, line 203
and the last lines from the trace:
…/django/forms/models.py in _construct_form
- form = super(BaseInlineFormSet, self)._construct_form(i, **kwargs)
…/django/utils/datastructures.py in getitem
- pk = self.data[pk_key]
In the end it was a matter of timing. When deleting only a single child object out of many, there was no problem. If I was deleting too many child objects at once, the error could happen, because the delete action was attempting to reference ids that were not around. This is why nothing worked, not signals, not [object]_set. I fixed it by using jquery to set a hidden variable in the edit form for the child object, which caused the object to first process the update (slowing down it’s processing) and THEN the delete.