Search code examples
djangodjango-modelsdjango-formsmodelform

ValueError at /accounts/register. The User could not be created because the data didn't validate. (django model form)


I don't understand why this error would occur. So, here's my very simple user model:

from django.db import models
from django.contrib.auth.models import AbstractUser

# Create your models here.
class User(AbstractUser):
    pass

My Model Form:

class RegistrationForm(forms.ModelForm):
    password1 = forms.CharField(label='Password', widget=forms.PasswordInput)
    password2 = forms.CharField(label='Cofirm Password', widget=forms.PasswordInput)

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

    def clean_password(self):
        password1 = self.cleaned_data.get("password1")
        password2 = self.cleaned_data.get("password2")
        if password1 and password2 and password1 != password2:
            return False
        return True

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

And my view where i am calling the form.save() method:

class Register(View):
    template = 'application/register.html'
    success_url = 'application:index'

    def get(self, request):
        ctx = {
            'form': RegistrationForm(),
        }
        return render(request, self.template, ctx)

    def post(self, request):
        form = RegistrationForm(request.POST)
        instance = form.save(commit=False)
        if not form.is_valid():
            ctx = {
                'form': RegistrationForm(),
            }
            return render(request, self.template, ctx)
        instance.save()
        login(request, instance)
        return redirect(self.success_url)

Can someone please help me understand what i have done wrong here??

Thank you


Solution

  • You cannot run instance = form.save(commit=False) before .is_valid().

    Validate the form first then create the User instance. I've create a route for you to return the errors back if the form does not validate.

     def post(self, request):
        form = RegistrationForm(request.POST)
        if form.is_valid():
            instance = form.save()
            login(request, instance)
            return redirect(self.success_url)
        ctx = {
           'form': form,
        }
        return render(request, self.template, ctx)
    

    But make sure you render the errors in your template. An example of this would be:

    {% if form.errors %}
        {% for field in form %}
            {% for error in field.errors %}
                <div class="alert alert-danger">
                    <strong>{{ error|escape }}</strong>
                </div>
            {% endfor %}
        {% endfor %}
        {% for error in form.non_field_errors %}
            <div class="alert alert-danger">
                <strong>{{ error|escape }}</strong>
            </div>
        {% endfor %}
    {% endif %}