设置用户名时自定义clean()方法无效

时间:2017-06-14 13:28:05

标签: django forms validation

我有一个Django ModelForm,我想在验证时用一个用户实例设置一个ForeignKey,它隐藏在模板上,所以用户无法设置它。

观点:

def view1(request):
    if request.method == "POST":
        model1form = Model1Form(request.POST, request.FILES, user=request.user)
        if model1form.is_valid(): # fails here
            print "is valid"

形式:

class Model1Form(forms.ModelForm):

    class Meta:
        model = Model1
        fields = ['person_id', 'start_date', 'end_date']

    def __init__(self, *args, **kwargs):
        self.user = kwargs.pop('user', None)
        super(Model1Form, self).__init__(*args, **kwargs)

    def clean(self):
        cleaned_data = super(Model1Form, self).clean()

        start_date = cleaned_data.get("start_date")
        end_date = cleaned_data.get("end_date")

        username = self.user
        person = Person.objects.get(username_field=username)
        person_id = person.id
        print person_id # this prints fine

        # custom validation

        return cleaned_data

当我运行is_valid()时,这个clean方法失败了。但是在没有person_id的情况下运行正常。我究竟做错了什么?

型号:

class Model1(models.Model):

    person_id = models.ForeignKey(Person, null=True)
    start_date = models.DateField(null=True, blank=True)
    end_date = models.DateField(null=True, blank=True)

class Person(models.Model):

    first_name = models.CharField(max_length=15, default='')
    surname = models.CharField(max_length=30, default='')

    def __unicode__ (self):
        return self.first_name + ' ' + self.surname

这是错误的方法吗?

2 个答案:

答案 0 :(得分:2)

这里不需要隐藏的字段。将该字段保留在模型表单之外:

class Model1Form(forms.ModelForm):

    class Meta:
        model = Model1
        fields = ['start_date', 'end_date']

然后在您的视图中,使用commit=False保存,然后在实例上设置person

if request.method == "POST":
    model1form = Model1Form(request.POST, request.FILES, user=request.user)
    if model1form.is_valid(): # fails here
        instance = model1form.save(commit=False)
        instance.person = Person.objects.get(username_field=request.user)
        instance.save()

有关详细信息,请参阅the docs on the model form's save() method

完成此更改后,您可能会发现可以从表单的user方法中删除__init__

答案 1 :(得分:0)

首先让我们改变你的模型

class Model1(models.Model):    
    person = models.ForeignKey(Person, null=True)
    start_date = models.DateField(null=True, blank=True)
    end_date = models.DateField(null=True, blank=True)

以前你有person_id作为外键,这意味着你会有一个字段person_id_id,这很难读。

现在为表格。您需要确保您的fk是已清理数据的一部分。

class Model1Form(forms.ModelForm): 
    class Meta:
        model = Model1
        fields = ['start_date', 'end_date']  
    ...    
    def clean(self):
        cleaned_data = super(Model1Form, self).clean()
        ...
        username = self.user
        person = Person.objects.get(username_field=username)
        cleaned_data["person_id"] = person.id
        # if that doesn't work try cleaned_data["person"] = person
        ...
        return cleaned_data