Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Crispy forms throws VariableDoesNotExist error failed lookup for key [html5_required] on forms

I use allauth to sign in with emails and did a very basic custom login form and a template override for allauth and display the login form. Hitting the URL throws me straight into the exception:

Failed lookup for key [html5_required] in [{'True': True, 'False': False, 'None': None}, {'True': True, 'False': False, 'None': None, 'form': , 'form_show_errors': True, 'form_show_labels': True, 'label_class': '', 'field_class': ''}, {'forloop': {'parentloop': {}, 'counter0': 1, 'counter': 2, 'revcounter': 2, 'revcounter0': 1, 'first': False, 'last': False}, 'field': }, {}]

where I then have to continue the debugger twice to end up on the form.

I tried looking for this specific [html5_required] tag/key but haven't found anybody with the same missing key.

I removed the custom login form in settings.py to see if there is an issue but that didn't help.

I even tested it with a simple ```ModelForm`` just displaying two fields and got the same issue.

I have tried both: class based view (for Login) and a function based view (for Profile) and I am getting the same problem on both.

settings.py:


INSTALLED_APPS = [
   ...
   'crispy_forms',
   'allauth',
   'allauth.account',
   'allauth.socialaccount',
   'allauth.socialaccount.providers.google',
   ...
]

CRISPY_TEMPLATE_PACK = 'bootstrap4'

ACCOUNT_FORMS = {
   "login": "users.forms.CustomLoginForm"
}

forms.py

from django.utils.translation import ugettext as _
from django.urls import reverse_lazy
from allauth.account.forms import LoginForm, SignupForm
from crispy_forms.helper import FormHelper
from crispy_forms.layout import HTML
from django.forms import ModelForm

class CustomLoginForm(LoginForm):
    def __init__(self, *args, **kwargs):
        super(CustomLoginForm, self).__init__(*args, **kwargs)
        self.helper = FormHelper(self)
        # Add magic stuff to redirect back.
        self.helper.layout.append(
            HTML(
                "{% if redirect_field_value %}"
                "<input type='hidden' name='{{ redirect_field_name }}'"
                " value='{{ redirect_field_value }}' />"
                "{% endif %}"
            )
        )
        # Add password reset link.
        self.helper.layout.append(
            HTML(
                "<p><a class='button secondaryAction' href={url}>{text}</a></p>".format(
                    url=reverse_lazy('account_reset_password'),
                    text=_('Forgot Password?')
                )
            )
        )
        # Add submit button like in original form.
        self.helper.layout.append(
            HTML(
                '<button class="btn btn-primary btn-block" type="submit">'
                '%s</button>' % _('Sign In')
            )
        )

        self.helper.form_class = 'form-horizontal'
        self.helper.label_class = 'col-xs-2 hide'
        self.helper.field_class = 'col-xs-8'

templates/account/login.html

{% extends 'base.html' %}
{% load crispy_forms_tags %}


{% block content %}
  <h2>Login</h2>
  <form method="post">
    {% csrf_token %}
    {{ form|crispy }}
    <button class="btn btn-primary" type="submit">Login</button>
  </form>
{% endblock %}

the following code is the quick function based view for the profile which is using pretty much the same template:

#in urls.py: path('profile/', views.profile_view, name='user_profile')

#forms.py:
class UserProfileForm(ModelForm):

    class Meta:
        model = UserProfile
        fields = ('gender', 'birthdate')

#view.py:
def profile_view(request, *args, **kwargs):
    if request.method == "POST":
        form = UserProfileForm(request.POST)
        if form.is_valid():
            profile = form.save(commit=False)
            profile.user = request.user
            #profile.author = request.user
            #profile.published_date = timezone.now()
            profile.save()
            # TODO: add message or redirect ?!
    else:
        form = UserProfileForm()
    return render(request, 'profile.html', {'form': form})
{% extends 'base.html' %}
{% load crispy_forms_tags %}

{% block content %}

<h2>Profile</h2>
<form method="post">
  {% csrf_token %}
   {{ form|crispy }}
  <button class="btn btn-primary" type="submit">Update</button>
</form>
{% endblock %}

I don't understand why this key is missing, have i forgotten something or missed a configuration part?

the versions I am using:

  • django: 2.2.4
  • allauth: 0.39.1
  • crispy-forms: 1.7.2
  • python: 3.7.4

any guidance is really appreciated.

EDIT: I created a complete new project as a test with just crispy forms, a model with just 2 char fields, the ModelForm and template as mentioned above and receive the same issue.

So either I am doing something wrong/missing something or there is a problem, I also raised on their github issue https://github.com/django-crispy-forms/django-crispy-forms/issues/891

like image 606
Tomek Avatar asked Aug 12 '19 01:08

Tomek


2 Answers

I leave this as an "partial" answer since I do not know why or what the difference (in behavior) is but changing the call to the form in the template from:

{{ form|crispy }}

to

{% crispy form %}

got rid of the exception.

Then, as @skilled-in-blockchain mentions I can add the FormHelper to the form to make additional modifications. Thanks.

like image 149
Tomek Avatar answered Oct 15 '22 10:10

Tomek


Allow me to summarize, the issue on Github. Apparently, it's an issue with VS Code, as pointed out in this respond.

  1. It can be overcome by setting "django": false in your launch.json file. This however will no longer allow you to debug the rendering of the templates. In other words, setting break points in a template will no longer cause the debugger execution to pause at those points. For more info on debugging Django in VS Code, see this tutorial.

  2. As mentioned in the other post, switching from:

    {{ form|crispy }}
    

    to this

    {% crispy form %}
    

    also resolves the issue. However, this also requires you to use the FormHelper to insert buttons, or id's and more. Check out crispy form's documentation on the fundamentels how to use it.

like image 30
LuckyLub Avatar answered Oct 15 '22 08:10

LuckyLub