0

I was able to get the noRecaptcha form on my Django-allauth signup form, with the template using crispy forms. Using this answer

The question is really about forcing a field order on the crispy form layout, when the form is contained in django-allauth and does not specify a layout (per the author). So when overriding the signup form with a custom form of my own, I've tried to specify a layout, but am not sure I'm getting it recognized.
Combining other posts' answers:

from django import forms
from neatf.users.models import User

from nocaptcha_recaptcha.fields import NoReCaptchaField


class AllauthSignupForm(forms.Form):
    captcha = NoReCaptchaField()

    class Meta:
        model = User
        fields = ['username', 'email', 'password1', 'password2', 'captcha']
        field_order = ['username', 'email', 'password1', 'password2', 
                        'captcha']

    def signup(self, request, user):
        """ Required, or else it throws deprecation warnings """
        pass

I'm sure I have the wrong model referenced or it's simply ignored. The noRecaptcha field just sits happily at the top of the form, instead of at the bottom where I'd like it.

I've also tried using FormHelper - but must clearly be doing it wrong.

helper = FormHelper()
helper.form_class = '.form-inline'
helper.field_template = 'bootstrap4/layout/inline_field.html'
helper.layout = Layout(
    Fieldset('Contact data', 'username', 'email',),
    Fieldset('Password', 'password1', 'password2', 'captcha'))

I'd rather not rewrite the template, and hope there is a way to override the layout.

Community
  • 1
  • 1
wedward
  • 363
  • 2
  • 11

2 Answers2

0

Looking for a solution for this problem previously and used this method:

class AllauthSignupForm(forms.Form):
#https://developers.google.com/recaptcha/docs/display
#https://github.com/praekelt/django-recaptcha
captcha = ReCaptchaField(
    attrs={
        'theme' : 'clean',
        'size' : 'normal', #compact
    })
captcha.label = "Капча"

def __init__(self, *args, **kwargs):
    super(AllauthSignupForm, self).__init__(*args, **kwargs)
    original_fields = self.fields
    new_order = OrderedDict()
    for key in ['username', 'email', 'password1', 'password2', 'captcha']:
        if key in original_fields:
            new_order[key] = original_fields[key]
    self.fields = new_order

def signup(self, request, user):
    """ Required, or else it throws deprecation warnings """
    pass

Related answers:

How does Django Know the Order to Render Form Fields?

How can I order fields in Django ModelForm?

django-allauth: rearrange form fields (change order)

The solution works in version django-allauth==0.29 and doesn't work in new versions

(test for 0.30-0.31)

For the new version I can't set the order.

Community
  • 1
  • 1
  • I've got django-allauth (0.31.0), and using your code I got the recaptcha to move to the middle after email (displays order: username, email, recaptcha, password1, password2). An improvement, but not sure how to coerce the captcha to the end. Thanks – wedward Apr 18 '17 at 06:54
0

I found the answer to this in a reported issue on django-crispy in github. An "undocumented" feature (at that time) that I finally found in the docs on tags reference (not mentioned in layout sections).

Very simple and done on the template, requiring zero alterations of the forms.py:

signup.html

<form class="signup" id="signup_form" method="post" action="{% url 'account_signup' %}">
    {% csrf_token %}

    {{ form.username|as_crispy_field }}
    {{ form.email|as_crispy_field }}
    {{ form.password1|as_crispy_field }}
    {{ form.password2|as_crispy_field }}
    {{ form.captcha|as_crispy_field }}

    {% if redirect_field_value %}
        <input type="hidden" name="{{ redirect_field_name }}" value="{{ redirect_field_value }}"/>
    {% endif %}

    <script src='https://www.google.com/recaptcha/api.js'></script>
    <button class="btn btn-primary" type="submit">{% trans "Sign Up" %} &raquo;</button>
</form>

forms.py

from django import forms

from nocaptcha_recaptcha.fields import NoReCaptchaField


class AllauthSignupForm(forms.Form):
    captcha = NoReCaptchaField()

    def signup(self, request, user):
        """ Required, or else it throws deprecation warnings """
        pass

Hopefully this helps others.

wedward
  • 363
  • 2
  • 11