def test_set_view_normal(self):
     logged_in = self.client.login(username=self.normal['username'], password=self.normal['password'])
     self.assertTrue(logged_in)
     response = self.client.get('/set/')
     #attempt to log the user into admin
     self.assertEqual(response.status_code, 200)
     #even a post request should not succeed
     response = self.client.post('/set/', {'key': 'TEST_SETTING1', 'value': 'some random string', 'type': 'int'})
     self.assertEqual(response.status_code, 200)
     self.assertFalse(dynamic_settings.is_in_db('TEST_SETTING1'))
     self.assertEqual(dynamic_settings.TEST_SETTING1, 73)
     self.client.logout()
def dynamicsettings_index(request):
    """Renders a template in the admin to show a list of settings. 
    
    Params:
        - ``request``: a django http request object
        
    Returns:
        - a rendered template with the following variables
          defined in its response dict
              - ``dynamic_settings``: a list of settings represented
              as dict's with:
                  -  ``key`` - the name of the setting
                  - ``value`` - the value of the setting
                  - ``is_db`` - a boolean indicating if the setting is saved in the db or not
                  - ``type`` - the (Python) type of the setting as its string representation
                  - ``can_change`` - a boolean indicating if the setting can be saved in the database or not
            - ``settings_form_rendered``: rendered html of ``forms.SettingsForm``
    """
    keys = [key for key in settings.dict()]
    keys.sort()
    res = []
    for key in keys:  
        value = settings.get(key)
        if isinstance(value, (list, tuple, dict)):
            try:
                value = simplejson.dumps(value, indent=4)
            except TypeError:
                value = 'Not a serializable object'
        res.append({
            'key': key,
            'value': value,
            'in_db': settings.is_in_db(key),
            'type': type(settings.get(key)).__name__,
            'can_change': settings.can_change(key),
        })
    res.sort(key=lambda e: e['can_change'], reverse=True)
    form_dict =  {'settings_form': forms.SettingsForm()}
    form_dict.update(csrf_processor(request))
    settings_form_rendered = template.loader.render_to_string('dynamicsettings/settings_form.html', form_dict)
    content_dict = {
        'dynamic_settings': res,
        'settings_form_rendered': settings_form_rendered,
    }
    return shortcuts.render_to_response('dynamicsettings/settings.html', content_dict,
                                        context_instance=template.RequestContext(request))
 def clean(self):
     """
     a) Check if the setting was originally from the submitted type.
     Used to avoid abuse of the form by enabling disabled form 
     fields via firebug or similiar.
     b) Try to convert the value according to submitted type.
     Raises ValidiationError when type and value are not fitting
     each other (eg. value can;t be converted to type).
     c) check if the resulting value was actually changed  (and
     not yet in the database)
     """
     error_message_tmpl = 'A setting from type %s must be set to %s.'
     key = self.cleaned_data['key']
     value = self.cleaned_data['value']
     value_type = self.cleaned_data['type']
     if settings.can_change(key) is False:
         raise forms.ValidationError(_("This setting can not be changed."))
     #a)
     original_type = type(settings.__getattr__(key)).__name__
     if original_type!='NoneType' and value_type!=original_type:
         raise forms.ValidationError(_("You can not change the type of a setting which was not NoneType before."))
     #b)
     if value_type == 'NoneType':
         if value!='None':
             raise forms.ValidationError(_(error_message_tmpl % ('NoneType', '"None"')))
         self.cleaned_data['value'] = None
     elif value_type == 'bool':
         if value!='True' and value!='False':
             raise forms.ValidationError(_(error_message_tmpl % ('bool', '"True" or "False"')))
         if value!='True':
             self.cleaned_data['value'] = True
         elif value!='False':
             self.cleaned_data['value'] = False
     elif value_type == 'int':
         try:
             self.cleaned_data['value'] = int(value)
         except ValueError:
             raise forms.ValidationError(_(error_message_tmpl % ('int or long', 'a number')))
     elif value_type == 'int':
         try:
             self.cleaned_data['value'] = float(value)
         except ValueError:
             raise forms.ValidationError(_(error_message_tmpl % ('float', 'a number')))
     elif value_type == 'str':
         self.cleaned_data['value'] = value
     elif value_type == 'unicode':
         self.cleaned_data['value'] = unicode(value)
     elif value_type in ['tuple', 'list', 'dict']:
         try:
             self.cleaned_data['value'] = value = simplejson.loads(value)
         except ValueError:
             raise forms.ValidationError(_(error_message_tmpl % ('tuple, list or dict', 'a valid JSON string')))
         if value_type == 'tuple' and type(value).__name__!='tuple':
             try:
                 if type(value).__name__ == 'dict':
                     raise TypeError
                 self.cleaned_data['value'] = tuple(value)
             except (ValueError, TypeError):
                 raise forms.ValidationError(_(error_message_tmpl % ('tuple', 'a valid JSON string representing an Array (leading "["and traling "]")')))
         elif value_type == 'list' and type(value).__name__!='list':
             try:
                 if type(value).__name__ == 'dict':
                     raise TypeError
                 self.cleaned_data['value'] = list(value)
             except (ValueError, TypeError):
                 raise forms.ValidationError(_(error_message_tmpl % ('list', 'a valid JSON string representing an Array (leading "["and traling "]")')))
         elif value_type == 'dict' and type(value).__name__!='dict':
             try:
                 if type(value).__name__ == 'list':
                     raise TypeError
                 self.cleaned_data['value'] = dict(value)
             except (ValueError, TypeError):
                 raise forms.ValidationError(_(error_message_tmpl % ('dict', 'a valid JSON string representing an Object (leading "{"and traling "}")')))
     #c)
     value = self.cleaned_data['value']
     if not settings.is_in_db(key) and value==settings.__getattr__(key):
         raise forms.ValidationError(_('To save a setting in the database the value must have been changed from its original value.'))
     
     return self.cleaned_data
 def test_set_view_staff(self):
     logged_in = self.client.login(username=self.staff['username'], password=self.staff['password'])
     self.assertTrue(logged_in)
     response = self.client.get('/set/')
     self.assertEqual(response.status_code, 405)
     
     #check first setting
     response = self.client.post('/set/', {'key': 'TEST_SETTING1', 'value': '42', 'type': 'int'})
     self.assertEqual(response.status_code, 200)
     content_json = simplejson.loads(response.content)
     self.assertEqual(content_json['status'], 'success')
     self.assertEqual(content_json['value'], 42)
     self.assertEqual(content_json['type'], 'int')
     self.assertTrue(dynamic_settings.is_in_db('TEST_SETTING1'))
     #change to non int
     response = self.client.post('/set/', {'key': 'TEST_SETTING1', 'value': 'some random string', 'type': 'int'})
     self.assertEqual(response.status_code, 200)
     content_json = simplejson.loads(response.content)
     self.assertEqual(content_json['status'], 'error')
     self.assertTrue(dynamic_settings.is_in_db('TEST_SETTING1'))
     #check that the old value is still saved
     self.assertEqual(dynamic_settings.TEST_SETTING1, 42)
     dynamic_settings.reset('TEST_SETTING1')
     self.assertFalse(dynamic_settings.is_in_db('TEST_SETTING1'))
     self.assertEqual(dynamic_settings.TEST_SETTING1, 73)
     
     #check second setting
     response = self.client.post('/set/', {'key': 'TEST_SETTING2', 'value': 'my_custom_string', 'type': 'str'})
     self.assertEqual(response.status_code, 200)
     content_json = simplejson.loads(response.content)
     self.assertEqual(content_json['status'], 'success')
     self.assertEqual(content_json['value'], 'my_custom_string')
     self.assertEqual(content_json['type'], 'str')
     self.assertTrue(dynamic_settings.is_in_db('TEST_SETTING2'))
     #change to the type
     response = self.client.post('/set/', {'key': 'TEST_SETTING2', 'value': '123', 'type': 'int'})
     self.assertEqual(response.status_code, 200)
     content_json = simplejson.loads(response.content)
     self.assertEqual(content_json['status'], 'error')
     self.assertTrue(dynamic_settings.is_in_db('TEST_SETTING2'))
     #check that the old value is still saved
     self.assertEqual(dynamic_settings.TEST_SETTING2, 'my_custom_string')
     dynamic_settings.reset('TEST_SETTING2')
     self.assertFalse(dynamic_settings.is_in_db('TEST_SETTING2'))
     self.assertEqual(dynamic_settings.TEST_SETTING2, 'a string')
     
     #check third setting
     response = self.client.post('/set/', {'key': 'TEST_SETTING3', 'value': '[4,5]', 'type': 'list'})
     self.assertEqual(response.status_code, 200)
     content_json = simplejson.loads(response.content)
     self.assertEqual(content_json['status'], 'success')
     self.assertEqual(content_json['value'].replace('\n','').replace(' ',''), '[4,5]')
     self.assertEqual(content_json['type'], 'list')
     self.assertTrue(dynamic_settings.is_in_db('TEST_SETTING3'))
     #change the value to sth which doesnt look like a list
     response = self.client.post('/set/', {'key': 'TEST_SETTING3', 'value': '{"d": 123}', 'type': 'list'})
     self.assertEqual(response.status_code, 200)
     content_json = simplejson.loads(response.content)
     self.assertEqual(content_json['status'], 'error')
     self.assertTrue(dynamic_settings.is_in_db('TEST_SETTING3'))
     #check that the old value is still saved
     self.assertEqual(dynamic_settings.TEST_SETTING3, [4, 5])
     dynamic_settings.reset('TEST_SETTING3')
     self.assertFalse(dynamic_settings.is_in_db('TEST_SETTING3'))
     self.assertEqual(dynamic_settings.TEST_SETTING3, [1, 2, 3])
     
     #check fourth setting
     response = self.client.post('/set/', {'key': 'TEST_SETTING4', 'value': '{"d": 123, "abc": "string", "l": []}', 'type': 'dict'})
     self.assertEqual(response.status_code, 200)
     content_json = simplejson.loads(response.content)
     self.assertEqual(content_json['status'], 'success')
     self.assertEqual(content_json['type'], 'dict')
     self.assertTrue(dynamic_settings.is_in_db('TEST_SETTING4'))
     #change the value and type to something completely different
     response = self.client.post('/set/', {'key': 'TEST_SETTING4', 'value': '123', 'type': 'long'})
     self.assertEqual(response.status_code, 200)
     content_json = simplejson.loads(response.content)
     self.assertEqual(content_json['status'], 'error')
     self.assertTrue(dynamic_settings.is_in_db('TEST_SETTING4'))
     #check that the old value is still saved
     self.assertEqual(dynamic_settings.TEST_SETTING4, {"d": 123, "abc": "string", "l": []})
     dynamic_settings.reset('TEST_SETTING4')
     self.assertFalse(dynamic_settings.is_in_db('TEST_SETTING4'))
     self.assertEqual(dynamic_settings.TEST_SETTING4, {'key': 'value', 'num': 3})
     
     #check last setting (NoneType - can be changed to anything)
     response = self.client.post('/set/', {'key': 'TEST_SETTING5', 'value': u'你好', 'type': 'unicode'})
     self.assertEqual(response.status_code, 200)
     content_json = simplejson.loads(response.content)
     self.assertEqual(content_json['status'], 'success')
     self.assertEqual(content_json['value'], u'你好')
     self.assertEqual(content_json['type'], 'unicode')
     self.assertTrue(dynamic_settings.is_in_db('TEST_SETTING5'))
     #check to another type (once a type is set it should not change anymore)
     response = self.client.post('/set/', {'key': 'TEST_SETTING5', 'value': '300', 'type': 'int'})
     self.assertEqual(response.status_code, 200)
     content_json = simplejson.loads(response.content)
     self.assertEqual(content_json['status'], 'error')
     self.assertTrue(dynamic_settings.is_in_db('TEST_SETTING5'))
     #change the type to list and value to something which doesnt look like a list
     response = self.client.post('/set/', {'key': 'TEST_SETTING5', 'value': '404', 'type': 'list'})
     self.assertEqual(response.status_code, 200)
     content_json = simplejson.loads(response.content)
     self.assertEqual(content_json['status'], 'error')
     self.assertTrue(dynamic_settings.is_in_db('TEST_SETTING5'))
     #check that the old value is still saved
     self.assertEqual(dynamic_settings.TEST_SETTING5, u'你好')
     dynamic_settings.reset('TEST_SETTING5')
     self.assertFalse(dynamic_settings.is_in_db('TEST_SETTING5'))
     self.assertEqual(dynamic_settings.TEST_SETTING5, None)
     self.assertEqual(type(dynamic_settings.TEST_SETTING5).__name__, 'NoneType')
     
     self.client.logout()