سؤال

In my registration, I am enforcing that email-id is unique. That is if a user exists with that email-id, I want to raise a forms.ValidationError.

Here is my form.py:

from django.contrib.auth.forms import UserCreationForm
from django.contrib.auth.models import User

class MyRegistrationForm(UserCreationForm):
    #define fields
    email=forms.EmailField(required=True)

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

    def clean_email(self):
            email = self.cleaned_data["email"]
            try:
                user = User.objects.get(email=email)
                print user.email
                print user.username
                raise forms.ValidationError("This email address already exists. Did you forget your password?")
            except User.DoesNotExist:
                return email

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

my view.py:

def register_user(request):
    if request.method=='POST':
        form=MyRegistrationForm(request.POST)
        if form.is_valid():
            form.save()
            messages.success(request, "Thank you for signing up")
            return HttpResponseRedirect("/accounts/register_success")

    args={}
    args['form']=MyRegistrationForm()
    return render(request,"register.html",args)

when I register a user with same email id, it does not throw validationError. but simply return the register.html but no duplicate user is added.

why is it not throwing validationError?

I added a couple of print statements in forms.py (above) to print the username and email that I get from User.object.get(email=email) and it correctly prints the name and email id of previously registered user. so the control proceeds till there but it is not throwing validationError

EDIT:

I also tried creating a brand new user, but having passoword fields Not match. still, I do not get any error message. but it simply redirects to register.html

EDIT:

template/register.html

{% extends "base.html" %}

{% block content %}


<h2>Register</h2>
<form action="" method="post">{% csrf_token %}

{{ form.as_p }}

<input type="submit" value="register"/>

</form>
{% endblock %}

In this template, error gets displayed automatically right above the field where the error occurs. I don't have to do {{ form.email.error }}. However, I do not have a way to customize the error. eg bold or some css to them. Is that possible?

هل كانت مفيدة؟

المحلول

Django forms catch ValidationError exception and adds error to form _errors dict. This code from django BaseForm._clean_fields method:

        try:
            # ...
            if hasattr(self, 'clean_%s' % name):
                value = getattr(self, 'clean_%s' % name)()
                self.cleaned_data[name] = value
        except ValidationError as e:
            self._errors[name] = self.error_class(e.messages)
            if name in self.cleaned_data:
                del self.cleaned_data[name]

So, by raising ValidationError exception you are telling django to add errors to cleaning field and make your form not valid.

You can access field error in template:

{{ form.field_name.errors }}

and iterate one field errors (django docs Customizing the form template):

{% if form.subject.errors %}
    <ol>
    {% for error in form.subject.errors %}
        <li><strong>{{ error|escape }}</strong></li>
    {% endfor %}
    </ol>
{% endif %}

and all fields errors (django docs Looping over the form’s fields):

{% for field in form %}
    {{ field.errors }}
    {{ field.label_tag }} {{ field }}
{% endfor %}

and display non field errors:

 {{ form.non_field_errors }}

update: you should add else block in view. Without else you are always create new form:

def register_user(request):
    if request.method=='POST':
        form=MyRegistrationForm(request.POST)
        if form.is_valid():
            form.save()
            messages.success(request, "Thank you for signing up")
            return HttpResponseRedirect("/accounts/register_success")
    else:
        form = MyRegistrationForm()

    args={}
    args['form'] = form
    return render(request,"register.html",args)
مرخصة بموجب: CC-BY-SA مع الإسناد
لا تنتمي إلى StackOverflow
scroll top