【问题标题】:Django, show ValidationError in templateDjango,在模板中显示 ValidationError
【发布时间】:2014-04-23 14:50:57
【问题描述】:

我创建了一个注册应用程序,用户可以在其中注册并提供用户名、电子邮件和密码。我所做的是确保电子邮件字段是唯一的(如您在下面的代码中所见)。但我不知道如何在用户输入已在使用的电子邮件地址时显示错误。

查看

from django.shortcuts import render
from django.shortcuts import render_to_response
from django.http import HttpResponseRedirect
from django.core.context_processors import csrf

from forms import RegistrationForm

# Create your views here.
def register_user(request):
    if request.method == 'POST':
        form = RegistrationForm(request.POST)
        if form.is_valid():
            form.save()
            return HttpResponseRedirect('../../membership/register_success')
        else:
            return HttpResponseRedirect('../../membership/register_failed')

    args = {}
    args.update(csrf(request))

    args['form'] = RegistrationForm()

    return render(request,'registration/registration_form.html', args)

def register_success(request):
    return render_to_response('registration/registration_success.html')

def register_failed(request):
    return render_to_response('registration/registration_failed.html')

表格

from django import forms
from django.contrib.auth.models import User
from django.contrib.auth.forms import UserCreationForm
from django.utils.translation import ugettext_lazy as _

    # forms.py
    class RegistrationForm(UserCreationForm):
        email = forms.EmailField(required=True)

        class Meta:
            model = User
            fields = ('username', 'email', 'password1', 'password2')

        def clean_email(self):
            email = self.cleaned_data.get('email')
            username = self.cleaned_data.get('username')

            if email and User.objects.filter(email=email).exclude(username=username).count():
                raise forms.ValidationError(_("This email address is already in use. Please supply a different email address."))
            return email

        def save(self, commit=True):
            user = super(RegistrationForm, self).save(commit=False)
            user.email = self.cleaned_data['email']
            if commit:
                user.save()
            return user

registration.html

    {% extends "base.html" %}
    {% block title %}Registration{% endblock %}

    {% block content %}

            <h1>Registration</h1>

            {% if form.errors %}
            <h1>ERRORRRRRR same email again???</h1>
            {% endif %}

            {% if registered %}
            <strong>thank you for registering!</strong>
            <a href="../../">Return to the homepage.</a><br />
            {% else %}
            <strong>register here!</strong><br />

            <form method="post" action="/membership/register/">{% csrf_token %}
                {{ form }}
                <input type="submit" name="submit" value="Register" />
            </form>
            {% endif %}

    {% endblock %}

【问题讨论】:

    标签: django forms email unique validationerror


    【解决方案1】:

    您在模板上显示带有{{ form }} 的表单。默认情况下,它本身应该显示所有验证错误,但在您的情况下,如果表单无效,您将重定向到其他页面。因此,除非您使用 GET 参数传递错误,否则您永远无法显示错误。您可以将视图更改为此以获取注册页面本身的错误 -

    def register_user(request):
        args = {}
        if request.method == 'POST':
            form = RegistrationForm(request.POST)
            if form.is_valid():
                form.save()
                return HttpResponseRedirect('../../membership/register_success')
        else:
            form = RegistrationForm()
        args['form'] = form
    
        return render(request,'registration/registration_form.html', args)
    

    其工作原理是,如果请求方法是 POST,则使用 POST 数据启动表单,然后使用 is_valid() 调用对其进行验证,因此如果表单对象无效,则现在表单对象会显示验证错误消息。如果有效,则保存并重定向。如果无效,则进入args['form'] = form 部分,其中带有错误消息的表单对象被设置为上下文,然后传递给渲染。

    如果请求方法不是POST,则实例化一个没有数据的表单对象并传递给render()

    现在,如果有任何错误,您的模板应该在每个字段下方显示所有错误消息。

    【讨论】:

    • 我遇到了同样的错误,但我不明白args 是如何参与其中的。为什么 args 甚至存在?模板中没有用到。
    【解决方案2】:

    forms.py

    from django import forms
    
    class RegistForm(forms.Form):
    
        name = forms.CharField(required=True)
        email = forms.EmailField(required=True)
        password = forms.CharField(required=True)
    

    views.py

    from django.shortcuts import render
    from django.views.generic import TemplateView
    import forms
    
    class Register(TemplateView):
    
        def get(self, request):
            return render(request, 'register.html', {})
    
        def post(self, request):
            form = forms.RegistForm(request.POST)
            if form.is_valid():
                print(1)
            else:
                print(form.errors)
            content = {'form':form};
            return render(request, 'register.html', content)
    

    register.html

        <form action="{% url 'register' %}" method="post">
    
            {% csrf_token %}
    
            <fieldset>
              <label for="name">Name:</label>
              <input type="text" id="name" name="name" value="">
              {{ form.errors.name }}
    
              <label for="mail">Email:</label>
              <input type="text" id="mail" name="email">
              {{ form.errors.email }}
    
              <label for="password">Password:</label>
              <input type="password" id="password" name="password">
              {{ form.errors.password }}
            </fieldset>
    
            <button type="submit">Sign Up</button>
    
            <p class="message">Already registered? <a href="{% url 'login' %}">Login</a></p>
    
        </form>
    

    ** 随意复制代码,尽情享受吧! **

    【讨论】:

      【解决方案3】:

      为什么不做这样的事情:

      ...
      if User.objects.filter(email=email):
          raise forms.ValidationError(_("This email address is already in use. Please supply a different email address."))
      return email
      ...
      

      如果用户已经注册,让它引发验证错误。如果您不希望它这样做,您可以执行以下操作:

      ...
      email_exists = User.objects.filter(email=email):
      if email_exists and email_exists.username != username:
          raise forms.ValidationError(_("This email address is already in use. Please supply a different email address."))
      return email
      ...
      

      要显示表单错误,请使用form.is_valid() 确保它通过验证。 Django 为custom validations 说以下内容:

      Note that any errors raised by your Form.clean() override will not be associated with any field in particular. They go into a special “field” (called __all__), which you can access via the non_field_errors() method if you need to. If you want to attach errors to a specific field in the form, you need to call add_error().

      然后在您的模板中,您可以使用{{ form.non_field_errors }} 等内容。

      请参阅 Django 文档中的此部分,位于 Using a form in a viewCustomizing the form template:
      https://docs.djangoproject.com/en/dev/topics/forms/

      【讨论】:

      • 感谢您的快速回复!问题是我无法管理“ValidationError”以在模板中显示消息。即({% if form.errors %}...)
      • 啊,它在 django 文档中。如果您在视图中使用form.is_valid(),则可以执行form.errors 和其他操作。查看我的更新回复。
      • 如果您使用form.is_valid() 在视图中检查验证,它应该显示在{% form.errors %} 中。我很好奇,所以如果可行,请随时通知我。
      • 问题是我确实在我的views.py 文件中使用了“form.is_valid()”。你可以在这里找到它pastebin.com/068mAnWh
      • 我在这里找到了答案:link我更新了我的回复。您需要致电add_error()non_field_errors()
      【解决方案4】:

      基于类的视图更容易。

      from django.views import generic
      from .forms import RegistrationForm
      
      class RegistrationView(generic.CreateView):
          template_class = 'registration/registration_form.html'
          form_class = RegistrationForm
          success_url = '/success/url'
      
          def form_valid(self, form):
              # add a log after save or whatever
              super(RegistrationView, self).form_valid(self, form)
      

      clean 方法是自动的,表单和消息会这样呈现, 基于类的视图让生活更轻松,您的代码更干燥。

      【讨论】:

        猜你喜欢
        • 2016-10-15
        • 2016-02-24
        • 2019-12-22
        • 2012-03-01
        • 2019-09-20
        • 2020-05-05
        • 2019-08-07
        • 1970-01-01
        相关资源
        最近更新 更多