Django

Code

Changeset 8597

Show
Ignore:
Timestamp:
08/26/08 15:19:12 (3 months ago)
Author:
jacob
Message:

Fixed #6209: handle BooleanFields in FormPreview and FormWizard. In the process, broke the the security hash calculation out to a helper function. Thanks to mcroydon and rajeshdhawan.

Files:

Legend:

Unmodified
Added
Removed
Modified
Copied
Moved
  • django/trunk/django/contrib/formtools/preview.py

    r8193 r8597  
    1010from django.template.context import RequestContext 
    1111from django.utils.hashcompat import md5_constructor 
     12from django.contrib.formtools.utils import security_hash 
    1213 
    1314AUTO_ID = 'formtools_%s' # Each form here uses this as its auto_id parameter. 
     
    9899    def security_hash(self, request, form): 
    99100        """ 
    100         Calculates the security hash for the given Form instance
     101        Calculates the security hash for the given HttpRequest and Form instances
    101102 
    102         This creates a list of the form field names/values in a deterministic 
    103         order, pickles the result with the SECRET_KEY setting and takes an md5 
    104         hash of that. 
    105  
    106         Subclasses may want to take into account request-specific information 
     103        Subclasses may want to take into account request-specific information, 
    107104        such as the IP address. 
    108105        """ 
    109         data = [(bf.name, bf.data or '') for bf in form] + [settings.SECRET_KEY] 
    110         # Use HIGHEST_PROTOCOL because it's the most efficient. It requires 
    111         # Python 2.3, but Django requires 2.3 anyway, so that's OK. 
    112         pickled = pickle.dumps(data, pickle.HIGHEST_PROTOCOL) 
    113         return md5_constructor(pickled).hexdigest() 
     106        return security_hash(request, form) 
    114107 
    115108    def failed_hash(self, request): 
  • django/trunk/django/contrib/formtools/tests.py

    r8046 r8597  
    55 
    66success_string = "Done was called!" 
    7 test_data = {'field1': u'foo', 
    8              'field1_': u'asdf'} 
    9  
    107 
    118class TestFormPreview(preview.FormPreview): 
     
    1411        return http.HttpResponse(success_string) 
    1512 
    16  
    1713class TestForm(forms.Form): 
    1814    field1 = forms.CharField() 
    1915    field1_ = forms.CharField() 
    20  
     16    bool1 = forms.BooleanField(required=False) 
    2117 
    2218class PreviewTests(TestCase): 
     
    2824        input_template = '<input type="hidden" name="%s" value="%s" />' 
    2925        self.input = input_template % (self.preview.unused_name('stage'), "%d") 
     26        self.test_data = {'field1':u'foo', 'field1_':u'asdf'} 
    3027 
    3128    def test_unused_name(self): 
     
    6057        # Pass strings for form submittal and add stage variable to 
    6158        # show we previously saw first stage of the form. 
    62         test_data.update({'stage': 1}) 
    63         response = self.client.post('/test1/', test_data) 
     59        self.test_data.update({'stage': 1}) 
     60        response = self.client.post('/test1/', self.test_data) 
    6461        # Check to confirm stage is set to 2 in output form. 
    6562        stage = self.input % 2 
     
    7875        # Pass strings for form submittal and add stage variable to 
    7976        # show we previously saw first stage of the form. 
    80         test_data.update({'stage': 2}) 
    81         response = self.client.post('/test1/', test_data) 
     77        self.test_data.update({'stage':2}) 
     78        response = self.client.post('/test1/', self.test_data) 
    8279        self.failIfEqual(response.content, success_string) 
    83         hash = self.preview.security_hash(None, TestForm(test_data)) 
    84         test_data.update({'hash': hash}) 
    85         response = self.client.post('/test1/', test_data) 
     80        hash = self.preview.security_hash(None, TestForm(self.test_data)) 
     81        self.test_data.update({'hash': hash}) 
     82        response = self.client.post('/test1/', self.test_data) 
    8683        self.assertEqual(response.content, success_string) 
    8784 
     85    def test_bool_submit(self): 
     86        """ 
     87        Test contrib.formtools.preview form submittal when form contains: 
     88        BooleanField(required=False) 
     89 
     90        Ticket: #6209 - When an unchecked BooleanField is previewed, the preview 
     91        form's hash would be computed with no value for ``bool1``. However, when 
     92        the preview form is rendered, the unchecked hidden BooleanField would be 
     93        rendered with the string value 'False'. So when the preview form is 
     94        resubmitted, the hash would be computed with the value 'False' for 
     95        ``bool1``. We need to make sure the hashes are the same in both cases. 
     96 
     97        """ 
     98        self.test_data.update({'stage':2}) 
     99        hash = self.preview.security_hash(None, TestForm(self.test_data)) 
     100        self.test_data.update({'hash':hash, 'bool1':u'False'}) 
     101        response = self.client.post('/test1/', self.test_data) 
     102        self.assertEqual(response.content, success_string) 
     103 
  • django/trunk/django/contrib/formtools/wizard.py

    r8193 r8597  
    1313from django.template.context import RequestContext 
    1414from django.utils.hashcompat import md5_constructor 
     15from django.contrib.formtools.utils import security_hash 
    1516 
    1617class FormWizard(object): 
     
    141142        Calculates the security hash for the given HttpRequest and Form instances. 
    142143 
    143         This creates a list of the form field names/values in a deterministic 
    144         order, pickles the result with the SECRET_KEY setting and takes an md5 
    145         hash of that. 
    146  
    147144        Subclasses may want to take into account request-specific information, 
    148145        such as the IP address. 
    149146        """ 
    150         data = [(bf.name, bf.data or '') for bf in form] + [settings.SECRET_KEY] 
    151         # Use HIGHEST_PROTOCOL because it's the most efficient. It requires 
    152         # Python 2.3, but Django requires 2.3 anyway, so that's OK. 
    153         pickled = pickle.dumps(data, pickle.HIGHEST_PROTOCOL) 
    154         return md5_constructor(pickled).hexdigest() 
     147        return security_hash(request, form) 
    155148 
    156149    def determine_step(self, request, *args, **kwargs):