Skip to content

Commit

Permalink
Report serverside errors in register form
Browse files Browse the repository at this point in the history
  • Loading branch information
dentuk committed May 11, 2014
1 parent dc6a97b commit ff78aec
Show file tree
Hide file tree
Showing 3 changed files with 105 additions and 55 deletions.
99 changes: 45 additions & 54 deletions resrc/userprofile/forms.py
Original file line number Diff line number Diff line change
Expand Up @@ -6,79 +6,70 @@
from django.contrib.auth import authenticate

from crispy_forms.helper import FormHelper
from crispy_forms_foundation.layout import Layout, Row, Div, Fieldset, Submit, Field, HTML
from crispy_forms_foundation.layout import Layout, Row, Column, Div, Fieldset, Submit, Field, HTML

from captcha.fields import CaptchaField
from django.conf import settings

class AbideCrispyField(Field):
template = 'abide_crispy_field.html'

def __init__(self, *args, **kwargs):
clientside_error = kwargs.pop('clientside_error', None)
super(AbideCrispyField, self).__init__(*args, **kwargs)
self.clientside_error = clientside_error

def render(self, form, form_style, context, *args, **kwargs):
if self.clientside_error is not None:
context['clientside_error'] = self.clientside_error
return super(AbideCrispyField, self).render(form, form_style, context, *args, **kwargs)

class LoginForm(forms.Form):
username = forms.CharField(max_length=30)
password = forms.CharField(max_length=76, widget=forms.PasswordInput)


class RegisterForm(forms.Form):
email = forms.EmailField(label='email')
username = forms.CharField(label='username', max_length=30)
email = forms.EmailField(label='email', widget=forms.TextInput(attrs={'required':''}))
username = forms.CharField(label='username', max_length=30, widget=forms.TextInput(attrs={'required':''})
)
password = forms.CharField(
label='password', max_length=76, widget=forms.PasswordInput)
label='password', max_length=76, widget=forms.PasswordInput(attrs={'required':''})
)
password_confirm = forms.CharField(
label='confirm password', max_length=76, widget=forms.PasswordInput)
label='confirm password', max_length=76, widget=forms.PasswordInput(attrs={'required':''})
)
captcha = CaptchaField()

def __init__(self, *args, **kwargs):
self.helper = FormHelper()
self.helper.form_method = 'post'

self.helper.layout = Layout(
HTML('\
<div class="row">\
<div class="columns large-6">\
<label for="id_username" class="requiredField">\
username\
</label>\
<input id="id_username" maxlength="30" name="username" type="text" required pattern="username"/>\
<small class="error">3-30 characters, a-z A-Z 0-9 _ .</small>\
</div>\
<div class="columns large-6">\
<label for="id_email" class="requiredField">\
email\
</label>\
<input id="id_email" name="email" type="email" required/>\
<small class="error">A valid email address is required.</small>\
</div>\
</div>\
\
<div class="row">\
<div class="columns large-6">\
<label for="id_password" class="requiredField">\
password\
</label>\
<input id="id_password" maxlength="76" name="password" type="password" required/>\
</div>\
<div class="columns large-6">\
<label for="id_password_confirm" class="requiredField">\
confirm password\
</label>\
<input id="id_password_confirm" maxlength="76" name="password_confirm" type="password" required pattern="pass_confirm"/>\
<small class="error">password mismatch</small>\
</div>\
</div>\
\
<div class="row">\
<div class="columns large-2">\
'),
Field('captcha'),
HTML('\
</div>\
<div class="columns large-4">\
<input type="submit" name="submit" value="Register" class="submit button" id="register"/>\
<a href="/" class="button secondary">Cancel</a>\
</div>\
</div>\
\
</form>\
')
Row(
Column(
AbideCrispyField('username', pattern='username', clientside_error='3-30 characters a-z A-Z 0-9 _ .'),
css_class='large-6'
),
Column(
AbideCrispyField('email', clientside_error='A valid email address is required.'),
css_class='large-6'
)
),
Row(
Column(AbideCrispyField('password', clientside_error='A password is required.'), css_class='large-6'),
Column(
AbideCrispyField('password_confirm', pattern='pass_confirm', clientside_error='Password mismatch.'),
css_class='large-6'
)
),
Row(
Column(AbideCrispyField('captcha'), css_class='large-2'),
Column(
Submit('submit', 'Register'),
HTML('<a href="/" class="button secondary">Cancel</a>'),
css_class='large-4'
)
)
)
super(RegisterForm, self).__init__(*args, **kwargs)

Expand Down
50 changes: 50 additions & 0 deletions templates/abide_crispy_field.html
Original file line number Diff line number Diff line change
@@ -0,0 +1,50 @@
{% load crispy_forms_field %}

{% if field.is_hidden %}
{{ field }}
{% else %}
<div id="div_{{ field.auto_id }}" class="holder{% if wrapper_class %} {{ wrapper_class }}{% endif %}{% if field.errors and form_show_errors %} error{% endif %}{% if field|is_checkbox %} checkbox{% endif %}{% if field.css_classes %} {{ field.css_classes }}{% endif %}">{% spaceless %}

{% if field.label %}
{% if field|is_checkbox %}
{% crispy_field field %}
{% endif %}

<label for="{{ field.id_for_label }}" {% if field.field.required %}class="required"{% endif %}>
{{ field.label|safe }}{% if field.field.required %}<span class="asterisk">*</span>{% endif %}
</label>
{% endif %}

{% if field|is_checkboxselectmultiple %}
{% load l10n %}
<ul>{% for choice in field.field.choices %}<li>
<label for="id_{{ field.html_name}}_{{ forloop.counter }}"{% if flat_attrs %} {{ flat_attrs|safe }}{% endif %}>
<input type="checkbox"{% if choice.0 in field.value or choice.0|stringformat:"s" in field.value or choice.0|stringformat:"s" == field.value|stringformat:"s" %} checked="checked"{% endif %} name="{{ field.html_name }}" id="id_{{ field.html_name }}_{{ forloop.counter }}" value="{{ choice.0|unlocalize }}">
{{ choice.1|unlocalize }}
</label>
</li>{% endfor %}</ul>
{% endif %}

{% if not field|is_checkbox and not field|is_checkboxselectmultiple %}
{% crispy_field field %}
{% endif %}

{% if form_show_errors %}
{% for error in field.errors %}
<small id="error_{{ forloop.counter }}_{{ field.auto_id }}" class="error serverside">
{{ error }}
</small>
{% endfor %}
{% endif %}

{% if clientside_error %}
<small id="clientside_error_{{ field.auto_id }}" class="error clientside">
{{ clientside_error }}
</small>
{% endif %}

{% if field.help_text %}
<div id="hint_{{ field.auto_id }}" class="hint">{{ field.help_text|safe }}</div>
{% endif %}
{% endspaceless %}</div>
{% endif %}
11 changes: 10 additions & 1 deletion templates/base.html
Original file line number Diff line number Diff line change
Expand Up @@ -130,7 +130,16 @@ <h1><a href="{% url "home" %}">reSRC</a></h1>
<script src="{% static "js/vendor/jquery-1.10.2.min.js" %}"></script>
<script src="{% static "js/foundation/foundation.min.js" %}"></script>
<script>
$(document).foundation();
$(document).foundation();
$(document).ready(function() {
$('.error:has(.serverside.error)')
.find('.clientside.error').css('display', 'none').end() // force clientside errors not to be shown yet
.find('input:not([disabled]), select:not([disabled]), textarea:not([disabled]), button:not([disabled])').one('focus', function() {
$(this).closest('.error:has(.error.serverside)').removeClass('error')
.find('.serverside').css('display', 'none').end() // force serverside not to be shown again
.find('.clientside').removeAttr('style'); // undo force clientside not to be shown yet
})
});
</script>

{% block last_body %}{% endblock %}
Expand Down

0 comments on commit ff78aec

Please sign in to comment.