Reputation: 1389
I have a lesson
model:
class Lesson(models.Model):
list_name = models.CharField(max_length=50, primary_key=True)
def __str__(self):
return self.list_name
A sound
model:
class Sound(models.Model):
sound_hash = models.CharField(max_length=40, primary_key=True, editable=False)
lessons = models.ManyToManyField(Lesson, verbose_name="associated lessons", related_name="words")
And a test_pair
model:
class TestPair(models.Model):
master_sound = models.ForeignKey(Sound, related_name="used_as_master")
user_sound = models.ForeignKey(Sound, related_name="used_as_user")
My form looks something like this:
class SoundTestPairForm(ModelForm):
user_sounds = forms.ModelMultipleChoiceField(Sound.objects.all())
class Meta:
model = TestPair
fields = ['master_sound']
def __init__(self, *args, **kwargs):
super(SoundTestPairForm, self).__init__(*args, **kwargs)
self.fields['master_sound'] = forms.CharField()
self.fields['master_sound'].widget.attrs['readonly'] = 'readonly'
def clean(self):
cleaned_data = super(SoundTestPairForm, self).clean()
if 'user_sounds' not in cleaned_data.keys():
raise forms.ValidationError('You must select at least one sound to be compared')
cleaned_data['master_sound'] = Sound.objects.get(pk=self.fields['master_sound'])
return cleaned_data
This is throwing a DoesNotExist
error. The traceback points to this line: cleaned_data['master_sound'] = Sound.objects.get(pk=self.fields['master_sound'])
The local vars are as follows:
self
<SoundTestPairForm bound=True, valid=True, fields=(master_sound;associated_test;associated_lesson;user_sounds)>
cleaned_data
{'associated_lesson': u'pooooooooooooooooooooooop',
'associated_test': u'cats a',
'master_sound': u'ad27ec5e0d048ddbb17d0cef0c7b9d4406a2c33',
'user_sounds': [<Sound: Pants>]}
But when I go to python manage.py shell
, and import my model:
Sound.objects.get(pk=u'ad27ec5e0d048ddbb17d0cef0c7b9d4406a2c33')
<Sound: oombah>
It hits the appropriate object.
This is something I've been dealing with for a long time, and it's super frustrating. I try to switch my logic around and ultimately it ends up throwing a DoesNotExist
error, regardless of what I try.
Does anyone have any ideas?
Upvotes: 0
Views: 221
Reputation: 1254
I think you should replace:
Sound.objects.get(pk=self.fields['master_sound'])
with:
Sound.objects.get(pk=cleaned_data['master_sound'])
When the Form is valid, cleaned_data
will include a key and value for all its fields and you can see that in your question as well (The local vars paragraph).
In general speaking you should do validation in the individual clean_<fieldname>
methods. So:
def clean_master_sound(self):
master_sound_key = self.cleaned_data.get('master_sound')
try:
master_sound=Sound.objects.get(pk=master_sound_key)
except Sound.DoesNotExist:
raise forms.ValidationError("Sound with id: %s does not exist", master_sound_key)
return master_sound
Upvotes: 3