模型和字段验证中的clean()方法

mem*_*elf 19 django

我的模型clean()方法和基本字段验证有问题.这是我的模型和clean()方法.

class Trial(models.Model):

    trial_start = DurationField()
    movement_start = DurationField()
    trial_stop = DurationField()


    def clean(self):
        from django.core.exceptions import ValidationError
        if not (self.movement_start >= self.trial_start):
            raise ValidationError('movement start must be >= trial start')
        if not (self.trial_stop >= self.movement_start):
            raise ValidationError('trial stop must be >= movement start')
        if not (self.trial_stop > self.trial_start):
            raise ValidationError('trial stop must be > trial start')
Run Code Online (Sandbox Code Playgroud)

我的clean()方法检查某些值是否在正确的范围内.如果用户忘记填写字段,例如movement_start,那么我收到错误:

can't compare datetime.timedelta to NoneType

我很惊讶我得到了这个错误,因为原始clean()函数应该捕获缺少的条目(毕竟movement_start是必填字段).那么如何基本检查缺失值,以及我的自定义检查值是否在某个范围内?这可以用模型的clean()方法完成,还是需要使用Forms

EDIT1使其更清晰:trial_start,movement_start并且trial_stop都是必填字段.我需要编写一个clean()方法,首先检查所有三个字段是否已填写完毕,然后检查这些值是否在某个范围内.

例如,以下代码无效,因为trial_start可能为空.我想避免检查每个字段的存在 - django应该为我做那个.

class TrialForm(ModelForm):

    class Meta:
        model = Trial

    def clean_movement_start(self):
        movement_start = self.cleaned_data["movement_start"]
        trial_start = self.cleaned_data["trial_start"]
        if not (movement_start >= trial_start):
            raise forms.ValidationError('movement start must be >= trial start')
        return self.cleaned_data["movement_start"] 
Run Code Online (Sandbox Code Playgroud)

EDIT2 我想将此检查添加到模型clean()方法的原因是,将自动检查在python shell上创建的对象的正确值.表单适用于视图,但我还需要对shell进行值检查.

mem*_*elf 8

我猜这是要走的路:

class TrialForm(ModelForm):

    class Meta:
        model = Trial

    def clean(self):

        data = self.cleaned_data
        if not ('movement_start' in data.keys() and 'trial_start' in data.keys()  and 'trial_stop' in data.keys()):
            raise forms.ValidationError("Please fill out missing fields.")

        trial_start = data['trial_start']
        movement_start = data['movement_start']
        trial_stop = data['trial_stop']

        if not (movement_start >= trial_start):
            raise forms.ValidationError('movement start must be >= trial start')

        if not (trial_stop >= movement_start):
            raise forms.ValidationError('trial stop must be >= movement start')

        if not (trial_stop > trial_start):
            raise forms.ValidationError('trial stop must be > trial start')

        return data
Run Code Online (Sandbox Code Playgroud)

编辑这种方法的缺点是,只有通过表单创建对象时,值检查才会起作用.不会检查在python shell上创建的对象.


Lys*_*roz 6

我知道这已经晚了,但要回答为什么最终来到这里的人可能会发生这种情况:没有“原始清洁”。clean 方法是自定义验证的挂钩,因此您是提供其代码的人。不确定 OP 如何使用 clean hook,但是:定义它之后,您应该调用full_clean()您的模型,以便 Django 完整地运行模型验证。请参阅文档中的详细信息,了解它调用不同验证方法的顺序,例如https://docs.djangoproject.com/en/1.11/ref/models/instances/#validating-objects(可能需要注意的是:full_clean()不是模型不会自动调用,save()这就是为什么当您使用 shell 并立即保存时您将跳过验证的部分原因)

(注意 ModelForms 也有各种验证步骤,并将调用模型的 full_clean:https://docs.djangoproject.com/en/1.11/topics/forms/modelforms/#validation-on-a-modelform