表单clean()方法以防止'无法分配无'

时间:2012-08-18 13:31:10

标签: django django-forms

我想为我的'添加tvshow表单'制作以下模板:标题字段和tvshow_id字段。用户可以在标题CharField中输入标题,并使用AJAX按钮从我的数据库中检索匹配项。单击匹配后,将使用一些jQuery魔法填充tvshow_id字段。如果没有,那也应该没问题,因为我的表单应该使用用户提供的标题字符串创建一个新的tvshow实例。

但是,我一直收到以下错误:

  

/ tvshows / create / season /

中的ValueError      

无法指定无:“Season.tvshow”不允许空值。

假设我有以下型号:

class Tvshow(models.Model):
    title = models.CharField(max_length = 255)

class Season(models.Model):
    tvshow = models.ForeignKey(Song)

这是我的表格。请注意,在我的表单中,我声明不需要tvshow,而根据我的模型,它是。这是因为否则,字段本身将引发ValidationError。

class SeasonModelForm(models.ModelForm):
    tvshow = forms.CharField(required = False)

    def clean_season(self):
        tvshow_id = self.cleaned_data['tvshow']
        if tvshow_id:
            try:
                return Tvshow.objects.get(pk = tvshow_id)
            except Tvshow.DoesNotExist:
                raise forms.ValidationError("No tvshow with this ID was found.")
        else: return None

    def clean(self):
        """Assign a tvshow in case there is no Tvshow yet."""
        cd = self.cleaned_data
        if not isinstance(cd['tvshow'], Tvshow):
            try:
                cd['title']
            except KeyError:
                raise forms.ValidationError("Please provide at least a tvshow title.")
            else:
                cd['tvshow'] = Tvshow(title = cd['title'])
                cd['tvshow'].save()
        return cd

我的猜测是Season.tvshow的验证发生在我的代码运行之前的某个地方,但我似乎无法追踪它。

我很想你的意见,提前谢谢。

2 个答案:

答案 0 :(得分:0)

您需要从tvshow_id返回clean_season的值。

答案 1 :(得分:0)

我设法通过让clean_season()返回一个空的Tvshow()实例来解决它,然后对clean()做了一些小改动。这不是我写过的最漂亮的代码,但它完成了工作。

def clean_season(self):
    """Must return a Song instance, whatever the cost."""
    tvshow_id = self.cleaned_data['tvshow']
    if tvshow_id:
        try:
            return Tvshow.objects.get(pk = tvshow_id)
        except Tvshow.DoesNotExist:
            raise forms.ValidationError("No tvshow with this ID was found.")
    else: return Tvshow()

def clean(self):
    """Create a tvshow in case there is no tvshow yet."""
    cd = super(SeasonMinimalModelForm, self).clean()
    if not cd['tvshow'].title:
        try:
            cd['title']
        except KeyError:
            raise forms.ValidationError("Please provide at least a title.")
        else:
            cd['tvshow'] = Tvshow(title = cd['title'])
            cd['tvshow'].save()
    return cd