Question

I would want to make register form and check if the user's email is a new one by checking the DB.

But the problem is that I don't know how to make it. I tried using unique=True to Field and clean_email() method.

I have 2 questions.

1) When ValidationError happens at the step of unique=True, how could I catch that error? should I override the clean_field() method of Model? And How could I make it?

2) how could I write efficient and nice code for this registration app?

Below are the source code i made.

# models.py
from django.db import models

class User(models.Model):
    university = models.ForeignKey('University')
    mail = models.EmailField(unique=True)
    password = models.CharField()
    nickname = models.CharField()


class University(models.Model):
    name = models.CharField()
    mail = models.CharField()


from django.forms import ModelForm

class LoginForm(ModelForm):
    class Meta:
        model = User
        fields = ('mail', 'password')

class RegisterForm(ModelForm):
    class Meta:
        model = User

    def clean_mail(): 
        data = self.cleaned_data['mail']
        if User.objects.filter(mail=data).exists():
            raise forms.ValidationError("This email is already exists")

# views.py

def register(request):
    if request.method == 'POST':
        ###
        if form.is_valid():

I am so confused to make this. I am waiting for a help Thanks in advance ;)

Was it helpful?

Solution

You don't catch that error. Django does it for you: when you call form.is_valid(), it calls each of the clean_field methods and catches any ValidationError exceptions, putting them into the form.errors attribute.

So, what you have is already fine.

Except for the major, huge, absolutely vital issue that you should never store passwords in plain text. Don't create your own standalone user class: inherit from AbstractBaseUser and use Django's built-in methods to create users and hash their passwords. You must not do it like this.

OTHER TIPS

First of All, Your clean_mail() should return self.cleaned_data['mail'] , if error is not raised. Although clean_mail is not required here

Secondly, Django will automatically check for uniqueness of the Email if you set unique=Ture in Model. An error would be raised if it is not unique. You can over-ride unique error text by providing that in ModelForm's Meta options.

e.g.

class RegisterForm(ModelForm):
    class Meta:
        model = User
        error_messages = {
            'mail': {
                'unique': _("This email already exists"),
            },
        }

Note: error_messages option has been added in django v1.6 only... For previous versions:

You can over-ride the field mail in the ModelForm directly. e.g Define at top of the ModelForm

class RegisterForm(ModelForm):
    mail = forms.EmailField(max_length=255, error_messages = { 'unique': 'xyz....',})
    class Meta:.......

you can find reference here:https://docs.djangoproject.com/en/1.5/ref/forms/fields/#error-messages

Take a quick look at the following page: https://docs.djangoproject.com/en/dev/ref/models/instances/

The section "Validating objects" guides you through the steps in model validation.

If you require single-column uniqueness on User.mail, simply add the keyword unique=True to the Charfield. The stock implementation of validate_unique() will handle this.

Licensed under: CC-BY-SA with attribution
Not affiliated with StackOverflow
scroll top