changeset 91:cad201e72d73

Added validation for the text_color and accent_color fields.
author Atul Varma <varmaa@toolness.com>
date Thu, 27 Mar 2008 17:52:19 -0700
parents f9c59266abaf
children c5d76a735410
files PersonasBackend/personas/forms.py PersonasBackend/personas/models.py
diffstat 2 files changed, 103 insertions(+), 20 deletions(-) [+]
line wrap: on
line diff
--- a/PersonasBackend/personas/forms.py	Thu Mar 27 16:45:46 2008 -0700
+++ b/PersonasBackend/personas/forms.py	Thu Mar 27 17:52:19 2008 -0700
@@ -1,6 +1,23 @@
 from django.newforms import ModelForm, ValidationError
 from PersonasBackend.personas import models
 
+def newforms_validator( func ):
+    """
+    Turns a framework-independent validator that throws a ValueError
+    into a newforms-style validator that throws a ValidationError.
+
+    This is needed because Django's admin interface currently uses
+    old-style forms.
+    """
+
+    def wrapper( *args, **kwargs ):
+        try:
+            func( *args, **kwargs )
+        except ValueError, e:
+            raise ValidationError( e.message )
+
+    return wrapper
+
 class PersonaForm( ModelForm ):
     """
     Form given to normal users who don't have the permission to
@@ -11,12 +28,22 @@
         model = models.Persona
         exclude = ["owner", "date_published", "popularity", "status"]
 
+    @newforms_validator
+    def _color_cleaner( self, value ):
+        models.ensure_color_is_valid( value )
+        return value
+
+    def clean_text_color( self ):
+        return self._color_cleaner( self.data["text_color"] )
+
+    def clean_accent_color( self ):
+        return self._color_cleaner( self.data["accent_color"] )
+
     def clean( self ):
-        try:
-            form_data = dict( self.cleaned_data )
-            form_data.update( self.files )
-            models.ensure_header_and_footer_are_valid( form_data )
-        except ValueError, e:
-            raise ValidationError( e.message )
+        form_data = dict( self.cleaned_data )
+        form_data.update( self.files )
+        newforms_validator(
+            models.ensure_header_and_footer_are_valid
+            )( form_data )
 
         return self.cleaned_data
--- a/PersonasBackend/personas/models.py	Thu Mar 27 16:45:46 2008 -0700
+++ b/PersonasBackend/personas/models.py	Thu Mar 27 17:52:19 2008 -0700
@@ -55,6 +55,51 @@
 from django.contrib.auth.models import User
 from django.contrib.sites.models import Site
 
+MAX_COLOR_LENGTH = 7
+
+def ensure_color_is_valid( color ):
+    """
+    Given a color string, raises a ValueError if the color isn't
+    formatted properly.
+
+    Examples:
+
+      >>> ensure_color_is_valid('blah')
+      Traceback (most recent call last):
+      ...
+      ValueError: The color must start with a '#'.
+
+      >>> ensure_color_is_valid('#aaaaaaa')
+      Traceback (most recent call last):
+      ...
+      ValueError: The color is too long.
+
+      >>> ensure_color_is_valid('#aaaaa')
+      Traceback (most recent call last):
+      ...
+      ValueError: The color is too short.
+
+      >>> ensure_color_is_valid('#aaazaa')
+      Traceback (most recent call last):
+      ...
+      ValueError: The character 'z' isn't valid.
+
+      >>> ensure_color_is_valid('#aaaaaa')
+      >>> ensure_color_is_valid('#FFFF11')
+    """
+
+    HEX_CHARS = "0123456789abcdef"
+
+    if not color.startswith("#"):
+        raise ValueError( "The color must start with a '#'." )
+    if len(color) > MAX_COLOR_LENGTH:
+        raise ValueError( "The color is too long." )
+    if len(color) < MAX_COLOR_LENGTH:
+        raise ValueError( "The color is too short." )
+    for char in color.lower()[1:MAX_COLOR_LENGTH]:
+        if char not in HEX_CHARS:
+            raise ValueError( "The character '%s' isn't valid." % char )
+
 def ensure_header_and_footer_are_valid( form_data ):
     """
     Given a dictionry that corresponds to the form data for a Persona,
@@ -106,19 +151,32 @@
                 "file for the %s." % name
                 )
 
-def header_and_footer_validator( field_data, all_data ):
+def oldforms_validator( func ):
     """
-    Old-style forms Django validator wrapper for
-    ensure_header_and_footer_are_valid().  This is needed because
+    Turns a framework-independent validator that throws a ValueError
+    into an oldforms-style validator that throws a ValidationError.
+
+    This is needed because
     Django's admin interface currently uses old-style forms.
     """
 
-    from django.core import validators
+    def wrapper( field_data, all_data ):
+        from django.core import validators
+
+        try:
+            func( field_data, all_data )
+        except ValueError, e:
+            raise validators.ValidationError( e.message )
 
-    try:
-        ensure_header_and_footer_are_valid( all_data )
-    except ValueError, e:
-        raise validators.ValidationError( e.message )
+    return wrapper
+
+@oldforms_validator
+def header_and_footer_validator( field_data, all_data ):
+    ensure_header_and_footer_are_valid( all_data )
+
+@oldforms_validator
+def color_validator( field_data, all_data ):
+    ensure_color_is_valid( field_data )
 
 def get_num_filled( arg1, arg2 ):
     """
@@ -286,15 +344,12 @@
         blank=True,
         )
 
-    MAX_COLOR_LENGTH = 7
-
-    # TODO: Ensure that text_color and accent_color validate properly.
-
     text_color = models.CharField(
         help_text=("The RGB color, as a #RRGGBB color hash, "
                    "of the color of text that will be displayed "
                    "on the persona."),
         max_length=MAX_COLOR_LENGTH,
+        validator_list=[color_validator],
         blank=False,
         default="#000000"
         )
@@ -304,6 +359,7 @@
                    "of the accent colors that will be displayed "
                    "on the persona."),
         max_length=MAX_COLOR_LENGTH,
+        validator_list=[color_validator],
         blank=False,
         default="#000000"
         )
@@ -620,12 +676,12 @@
         )
 
     text_color = models.CharField(
-        max_length=Persona.MAX_COLOR_LENGTH,
+        max_length=MAX_COLOR_LENGTH,
         null=True,
         )
 
     accent_color = models.CharField(
-        max_length=Persona.MAX_COLOR_LENGTH,
+        max_length=MAX_COLOR_LENGTH,
         null=True,
         )