【问题标题】:Django problem with validating forms验证表单的Django问题
【发布时间】:2011-05-09 15:51:28
【问题描述】:

我一直试图弄清楚所有这些验证是如何工作的,但我没有掌握它。我阅读了 djangoproject 上的极少数示例,但我缺少概念以及所有内容是如何联系在一起的。

如果你能看一下我的代码并重新排列应该是怎样的,以及一些解释,那就太棒了!

所以我想做一些非常简单的事情:只使用电子邮件登录。当用户键入他们的电子邮件时,我想检查它是否在数据库中,如果是,请登录。如果不是,我想提出一个错误'用户已经在数据库中'并建议此人去 /register

所以我目前拥有的是:

view.py:

def emailLogin(request, backend, extra_context=None, initial={}):

form = EmailLoginForm(initial=initial)
if request.method == 'POST':
    form = EmailLoginForm(initial=initial, data=request.POST)
    if form.is_valid():
        user = form.do_save()

        _no_pass_login(request, user) # my custom login
        return redirect('/')

    else:
        print ('not valid')

return render_jinja(request, 'registration/email_login_form.html',
        type="register",
        form = form
        )

forms.py

class EmailLoginForm(forms.Form):
    email = forms.EmailField()
    def do_save(self):
    try:
            u = User.objects.get(email=self.cleaned_data['email'])
        except :
            raise forms.ValidationError("Already in DB")

        return u

所以重点是我缺少概念——应该在哪里引发验证错误,视图还是表单?它上升到哪里?谁抓住了它?每个文件中需要导入的内容等。

这应该不会太难,但我现在完全迷失了,我没有可以分析和修改我的代码的示例,所以我在这里。

【问题讨论】:

    标签: django django-forms django-validation


    【解决方案1】:

    是的,您似乎确实遗漏了一些概念。

    这种类型的表单根本不应该有保存。 is_valid() 检查的全部意义在于捕获验证错误——因此它们应该由该调用引发。这样做的方法是在表单上定义clean 方法。在这种情况下,由于您只检查 email 字段,因此您定义了一个 clean_email 方法。该代码应该与您当前在 do_save 中获得的代码相同。

    现在,is_valid() 将返回 False。但是您的视图需要进行一些调整才能实际显示错误。首先,将else 阻止back 一个缩进级别,使其匹配if request.method == 'POST'。现在,代替 print 语句,将第一行 - form = EmailLoginForm(initial=initial) 移到那里。现在,当is_valid() 为 False 时,视图将直接落入 render_to_response,其中包含验证错误的已实例化表单。魔法!

    【讨论】:

    • 是与字段名相关的方法名,或者我可以使用def clean_myemailfunction(self):吗?
    • 我认为当表单已经无效(带有实例化表单和错误)时,他的代码将落入 render_to_response() 。所以我不认为你的第二段是必要的。我同意您在第 1 段中的建议。
    • @mgPePe 你必须使用clean_<fieldname>。这一切都在validating forms 上的文档中。
    • @Brian 是的,但推荐好的做法总是最好的。在这种情况下,OP 为 POST 实例化了两次表单,这是不必要的。
    • Thanx,仅供参考,表单不应该返回电子邮件而不是用户吗?这不是更多的“好习惯”吗?我想我应该做return self.cleaned_data['email']
    【解决方案2】:

    我认为这就是 Daniel 所说的,但如果您不知道具体发生了什么,可能会造成混淆。基本上,表单所做的就是验证您的数据。所有的保存都在视图中完成。

    view.py

    def emailLogin(request, backend, extra_context=None, initial={}):
    
        form = EmailLoginForm
        if request.method == 'POST':
            form = form(initial=initial, data=request.POST)
            if form.is_valid():
                _no_pass_login(request, user) # my custom login
                return redirect('/')
            else:
                print 'Form not valid'
    
        else:
            form = form(initial=initial)
    
    return render_jinja(request, 'registration/email_login_form.html',
        type="register",
        form = form
        )
    

    forms.py

    class EmailLoginForm(forms.Form):
    
        email = forms.EmailField()
    
        def clean_email(self, *args, **kwargs):
            email = self.cleaned_data['email']
            if User.objects.filter(email=email).count() > 0:
                raise ValidationError('User with email "%s" already exists' % email)
            return email
    

    【讨论】:

    • 不完全——clean_email 方法应该返回 email,而不是整个字典。
    • 好收获。其余的看起来如何?
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2014-08-16
    • 2013-11-05
    • 2011-07-14
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多