Search code examples
pythondjangodjango-crispy-formsdjango-1.7

Key error while using django crispy forms for login


I was trying to create a login form in django using crispy forms. During login authentication I have two fields: email_id and password. but in browser it only showing password field, and have following error:

Django version is 1.7

WARNING:root:Could not resolve form field 'email_id'.
Traceback (most recent call last):
  File "/usr/local/lib/python2.7/dist-packages/crispy_forms/utils.py", line 74, in render_field
    field_instance = form.fields[field]
KeyError: u'email_id'

The snapshot of the webpage being rendered is :

Snapshot of page being rendered

The model of the User for which I am trying to login is : model.py

class User(models.Model):
    user_id = models.AutoField(primary_key=True)
    title_id = models.ForeignKey('Title')
    first_name = models.CharField(max_length=100)
    middle_name = models.CharField(max_length=100)
    last_name = models.CharField(max_length=100)
    username = models.CharField(max_length=100, unique=True, default='')
    password = models.CharField(max_length=100)  # will be changed according to hash used
    mobile_number = models.CharField(max_length=10)
    alternate_number = models.CharField(max_length=10)
    email_id = models.EmailField()
    date_of_birth = models.DateField()
    profession_id = models.ForeignKey('Profession')
    house_no = models.CharField(max_length=100)
    city_id = models.ForeignKey('City')
    country_id = models.ForeignKey('Country')
    state_id = models.ForeignKey('State')
    locality_id = models.ForeignKey('Locality')

The class for login in the file view.py is:

class LoginView(generic.FormView):
    form_class = LoginForm
    success_url = reverse_lazy('profile')
    template_name = 'login.html'
    #model = User

    def form_valid(self, form):
        email_id = form.cleaned_data['email_id']
        password = form.cleaned_data['password']
        user = authenticate(email_id=email_id, password=password)
        if user is not None and user.is_active:
            login(self.request, user)
            return super(LoginView, self).form_valid(form)
        else:
            return self.form_invalid(form)

The class for login form in forms.py is:

class LoginForm(AuthenticationForm):
    def __init__(self, *args, **kwargs):
        super(LoginForm, self).__init__(*args, **kwargs)
        self.helper = FormHelper()
        self.helper.layout = Layout(
            'email_id',
            'password',
            ButtonHolder(
                Submit('login', 'Login', css_class= 'btn-primary')
            )
        )

Solution

  • From what I can see (I am taking an educated guess, as you have not included your imports anywhere), you're using django.contrib.auth.forms.AuthenticationForm as the parent class for your LoginForm class, which is being used in LoginView.

    The only two fields on the AuthenticationForm class are username and password, but you are trying to access an email_id field in your Layout object in LoginForm.__init__. This will not work, because there is no field named email_id to access.

    The password field happens to show up on your page because there is a password field on AuthenticationForm, but if you're wanting to add email_id then you will need to either:

    • add email_id as a form Field on your LoginForm class, or
    • create a ModelForm using your User model, or
    • read this guide on how to specify a custom user model, and the steps necessary to integrate with django's auth app (I think this is what you want)

    I am not sure whether you are trying to create a custom user model or not, but since you seem to be using the django.contrib.auth.authenticate function in your view (again, an educated guess, as there are no imports) then it seems that you're not following the correct pattern.