From feead29402128f39b0170da6cfa5323fea499af9 Mon Sep 17 00:00:00 2001 From: Bryan Date: Wed, 26 Feb 2014 03:13:27 -0500 Subject: [PATCH] updated Django form with honeypot from master and styled form errors. --- karmaworld/apps/courses/forms.py | 43 +++++++++++++++++--- karmaworld/apps/courses/models.py | 2 - karmaworld/assets/css/global.css | 5 ++- karmaworld/settings/common.py | 2 + karmaworld/templates/partial/add_course.html | 2 +- 5 files changed, 44 insertions(+), 10 deletions(-) diff --git a/karmaworld/apps/courses/forms.py b/karmaworld/apps/courses/forms.py index e2642d3..42c5066 100644 --- a/karmaworld/apps/courses/forms.py +++ b/karmaworld/apps/courses/forms.py @@ -2,9 +2,12 @@ # -*- coding:utf8 -*- # Copyright (C) 2012 FinalsClub Foundation +import random + from django.conf import settings from django.forms import ModelForm from django.forms import CharField +from django.forms.util import ErrorList from ajax_select.fields import AutoCompleteSelectField from ajax_select.fields import AutoCompleteSelectWidget @@ -13,7 +16,33 @@ from ajax_select_cascade.fields import AutoCompleteDependentSelectWidget from karmaworld.apps.courses.models import Course -class CourseForm(ModelForm): + +# Django hard codes CSS attributes into ModelForm returned ErrorList +# https://github.com/django/django/blob/1.5.5/django/forms/util.py#L54-L60 +# https://docs.djangoproject.com/en/1.5/ref/forms/api/#customizing-the-error-list-format +# so this unfortunately doesn't do anything with ModelForms: +# https://docs.djangoproject.com/en/1.5/ref/forms/api/#django.forms.Form.error_css_class +class CSSErrorList(ErrorList): + """ Override ErrorList classes. """ + def as_ul(self, *args, **kwargs): + errorhtml = super(CSSErrorList, self).as_ul(*args, **kwargs) + # insert ') + # replace hard coded "errorlist" with something in our CSS: + errorhtml = errorhtml.replace('errorlist', 'validation_error') + return errorhtml + + +class NiceErrorModelForm(ModelForm): + """ By default use CSSErrorList for displaying errors. """ + def __init__(self, *args, **kwargs): + if 'error_class' not in kwargs: + kwargs['error_class'] = CSSErrorList + super(NiceErrorModelForm, self).__init__(*args, **kwargs) + + +class CourseForm(NiceErrorModelForm): school = AutoCompleteSelectField( 'school', widget=AutoCompleteSelectWidget( @@ -32,7 +61,11 @@ class CourseForm(ModelForm): def __init__(self, *args, **kwargs): """ Add a dynamically named field. """ super(CourseForm, self).__init__(*args, **kwargs) - self.fields[settings.HONEYPOT_FIELD_NAME] = CharField(required=False) + # insert honeypot into a random order on the form. + idx = random.randint(0, len(self.fields)) + self.fields.insert(idx, settings.HONEYPOT_FIELD_NAME, + CharField(required=False, label=settings.HONEYPOT_LABEL) + ) class Meta: model = Course @@ -51,9 +84,7 @@ class CourseForm(ModelForm): hfn = settings.HONEYPOT_FIELD_NAME formhoneypot = cleaned_data.get(hfn, None) if formhoneypot and (formhoneypot != settings.HONEYPOT_VALUE): - # Highlight a failure to follow instructions. - # When the template dynamically generates the form, replace - # 'honeypot' with hfn - self._errors['honeypot'] = [u'You did not follow directions.'] + # Highlight the failure to follow instructions. + self._errors[hfn] = [settings.HONEYPOT_ERROR] del cleaned_data[hfn] return cleaned_data diff --git a/karmaworld/apps/courses/models.py b/karmaworld/apps/courses/models.py index 6ef836c..f04cf1e 100644 --- a/karmaworld/apps/courses/models.py +++ b/karmaworld/apps/courses/models.py @@ -19,8 +19,6 @@ from ajax_select import LookupChannel from ajax_select_cascade import DependentLookupChannel from ajax_select_cascade import register_channel_name -from karmaworld.utils.ajax_selects import register_channel_name - class SchoolManager(models.Manager): """ Handle restoring data. """ diff --git a/karmaworld/assets/css/global.css b/karmaworld/assets/css/global.css index ae7e083..822a67c 100644 --- a/karmaworld/assets/css/global.css +++ b/karmaworld/assets/css/global.css @@ -645,6 +645,10 @@ a.activity_target:hover .validation_error { color:red; } +ul.validation_error { + display: inline; + list-style-type: none; +} #add-note-form, #add-course-form, #edit-course-form { @@ -891,7 +895,6 @@ hr.midrule legend, label { font: 12px/2em "MuseoSlab-300"; - margin-top: 20px; } .qq-upload-button { diff --git a/karmaworld/settings/common.py b/karmaworld/settings/common.py index d47ff22..d5f9b85 100644 --- a/karmaworld/settings/common.py +++ b/karmaworld/settings/common.py @@ -381,6 +381,8 @@ TAGGIT_STOPWORDS = [u'a', u'an', u'and', u'be', u'from', u'of'] # https://github.com/sunlightlabs/django-honeypot HONEYPOT_FIELD_NAME = "instruction_url" # see that "_url"? bots gotta want that. HONEYPOT_VALUE = "" +HONEYPOT_LABEL = "Do not fill in this field:" +HONEYPOT_ERROR = "You did not follow directions." ########## END HONEYPOT CONFIGURATION diff --git a/karmaworld/templates/partial/add_course.html b/karmaworld/templates/partial/add_course.html index 7b52b58..2c2dbee 100644 --- a/karmaworld/templates/partial/add_course.html +++ b/karmaworld/templates/partial/add_course.html @@ -21,7 +21,7 @@ {% endfor %} - {{ course_form }} + {{ course_form.as_p }}
-- 2.25.1