From 41e482db57b018e588e84c49b7f3dbbd240c5ff2 Mon Sep 17 00:00:00 2001 From: Torsten Engelbrecht Date: Mon, 25 Apr 2011 11:13:02 +0800 Subject: [PATCH] update docs --- PKG-INFO | 2 +- README | 130 ++++++++++++++++++-------------- dynamicsettings/__init__.py | 96 +++++++++++++++++++---- dynamicsettings/app_settings.py | 10 ++- dynamicsettings/forms.py | 8 +- dynamicsettings/views.py | 76 +++++++++++++------ setup.py | 2 +- 7 files changed, 227 insertions(+), 97 deletions(-) diff --git a/PKG-INFO b/PKG-INFO index 750abc1..c694336 100644 --- a/PKG-INFO +++ b/PKG-INFO @@ -1,6 +1,6 @@ Name: django-minify Version: 0.1 -Summary: Application to handle settings within Django +Summary: Application to handle live settings within Django Home-page: Author: Sterno.Ru Author-email: sterno.beijing@gmail.com diff --git a/README b/README index 1347c7e..3926713 100644 --- a/README +++ b/README @@ -1,7 +1,3 @@ -.. _Python: http://www.python.org/ -.. _Django: http://www.djangoproject.com/ -.. _staticfiles app: http://headjs.com/ - ======================= django-dynamicsettings ======================= @@ -37,12 +33,9 @@ or -3. Usage +3. Setup ::::::::::::::::::::::::::::::::: -3.1. Setup ------------------------------- - If you installed *django-dynamic-settings* you can already use it like you are used to python modules. That lets you make advantage of the internal caching for settings. @@ -51,7 +44,7 @@ If you want to do more (save settings in the database, check settings in the admin, run tests) you need to do the following: -1.put it into your ``INSTALLED_APPS`` setting. Make sure +**1.** Put ``'dynamicsettings'`` into your ``INSTALLED_APPS``. Make sure ``django.contrib.admin`` (and requirements) is appearing in your ``INSTALLED_APPS`` setting as well, since its used by *django-dynamic-settings*: @@ -70,7 +63,7 @@ following: ) -2. Add a url handler to handle the admin views of +**2.** Add a url handler to handle the admin views of *django-dynamic-settings*. This is built-in into the standard django admin, so you could add something like this: @@ -87,9 +80,9 @@ django admin, so you could add something like this: 3. Add settings: If you have another app which has settings you want to include or -your custom app which is using *django-dynamic-settings* has -some custom settings you can include these modules to add them -to be handled by *django-dynamic-settings*. For example: +your custom app is using *django-dynamic-settings* and has +some custom settings, you can include these modules to be handled +by *django-dynamic-settings*: :: @@ -114,24 +107,22 @@ For example: This would make ``MY_SETTING`` and ``DEFAULT_CACHE_DURATION`` editable in the database. -There is one thing you need to keep in mind when making -settings editable via admin: -**App's which are not using django-dynamic-settings are not +**Note**: App's which are not using *django-dynamic-settings* are not affected by the changes. That includes for example Django itself. It doesn't make much sense to change a setting in the database via admin which is used internally by Django. It will simply have -no effect.** +no effect. So the project or app which will make usage of *django-dynamic-settings* great way of retrieving and setting the settings in the database should use *django-dynamic-settings* instead of the usual way of -retrieving settings via ``from django.conf import settings``. The +retrieving settings via ``from django.conf import settings``. See the next section for usage examples. -3.2. Using django-dynamic-settings ------------------------------------------------------------- +4. Usage +::::::::::::::::::::::::::::::::: *django-dynamic-settings* is used in a very similiar way you @@ -156,48 +147,77 @@ After that you can use settings as you are used to. Examples: login_redirect_url = settings.LOGIN_REDIRECT_URL my_custom_setting = settings.MY_SETTING - -Additionally you have access to the following methods: - -``settings.get(key, default)``: Retrieve a setting for a -particular name (``key``) or return the ``default`` -(``None`` if emitted). Works like the python built-in -``dict.get()`` method Example usage: -:: - login_redirect_url = settings.get('LOGIN_REDIRECT_URL', '/') - my_custom_setting = settings.get('MY_SETTING) +Additionally you have access to the following methods: +- ``settings.get(key, default)``: Retrieve a setting for a + particular name (``key``) or return the ``default`` + (``None`` if emitted). Works like the python built-in + ``dict.get()`` method Example usage: + + :: + + login_redirect_url = settings.get('LOGIN_REDIRECT_URL', '/') + my_custom_setting = settings.get('MY_SETTING) + + +- ``settings.set(key, value, type)``: This is setting a setting + specified by ``key`` directly in the database without using the + admin interface. ``value`` is the new value of the setting and + ``type`` the python type. If ``type`` is not explicitly given + it will try to resolve the type from the given `value``. Returns + the new value if setting was successful. Raises + KeyError if the setting is not allowed to be changed due to + not defining it in ``DYNAMICSETTINGS_INCLUDE_SETTINGS``. + Examples: + + :: + + login_redirect_url = settings.set('LOGIN_REDIRECT_URL', '/home/') + my_custom_setting = settings.set('MY_SETTING', 73, 'int') + + +- ``settings.reset(key)``: If you saved a setting in the database you + can reset it (giving the name of the setting) to its original value via + this method. This method returns ``True`` if the reset was successful + and ``False`` if not (setting wasn't saved to the database for example). + Examples: + + :: + + login_redirect_url = settings.set('LOGIN_REDIRECT_URL', '/home/') + settings.reset('LOGIN_REDIRECT_URL') + print settings.LOGIN_REDIRECT_URL + + +- ``settings.dict(keys)``: Returns a dict representation of the settings. + If ``keys`` is ommitted all settings which are included into *django-dynamic-settings* + are part of the dict. If you just want to retrieve particular settings + you can provide names of the settings within ``keys`` (a list of strings). + +- ``settings.is_in_db(key)``: Check if a particular setting given by + its name (``key``) is saved in the db or not. Returns ``True`` if + this is case, ``False`` otherwise. + +- ``settings.can_change(key)``: Check if a particular setting given by + its name (``key``) can be changed (and saved in the database). This + returns ``True`` if the setting is provided in ``DYNAMICSETTINGS_INCLUDE_SETTINGS``, + ``False`` otherwise. + + +5. Additional settings +::::::::::::::::::::::::::::::::: -``settings.set(key, value, type)``: This is setting a setting -specified by ``key`` directly in the database without using the -admin interface. ``value`` is the new value of the setting and -``type`` the python type. If ``type`` is not explicitly given -it will try to resolve the type from the given `value``. Returns -the new value if setting was successful. Raises -KeyError if the setting is not allowed to be changed due to -not defining it in ``DYNAMICSETTINGS_INCLUDE_SETTINGS``. -Examples: +Settings within *django-dynamic-settings* are cached in case you +are using Django's cache framework. To define the timeout for the +cached settings you can set ``DYNAMICSETTINGS_CACHE_TIMEOUT``: :: - login_redirect_url = settings.set('LOGIN_REDIRECT_URL', '/home/') - my_custom_setting = settings.set('MY_SETTING', 73, 'int') + DYNAMICSETTINGS_CACHE_TIMEOUT = 60 - -3.3. Complex usage ------------------------------- - - -3.4. Additional settings ------------------------------- - - - - - - - +.. _Python: http://www.python.org/ +.. _Django: http://www.djangoproject.com/ \ No newline at end of file diff --git a/dynamicsettings/__init__.py b/dynamicsettings/__init__.py index dcbe8f0..9dce5cf 100644 --- a/dynamicsettings/__init__.py +++ b/dynamicsettings/__init__.py @@ -19,11 +19,19 @@ #will not trigger exceptions when syncdb or runserver #see django.conf.LazySettings class LazyDynamicSettings(LazyObject): + """Lazy wrapper for DynamicSettings. + """ def _setup(self): self._wrapped = DynamicSettings() class DynamicSettings(object): + """A class which is handling the dynamic settings. + It is similiar to Django's own conf.settings Settings + class, but also providing cached settings, setting and + reseting a setting in the database, returning settings + as a dict. + """ def __init__(self): self._settings_cache_key = 'dynamicsettings.settings' @@ -32,9 +40,42 @@ def __init__(self): self._get_settings() def get(self, key, default=None): + """Get a setting value for a partcular key (setting name). + Works similiar to a dict's ``get`` method. + + Params: + - ``key``: the name of setting + - ``default`` (optional): a default value if the setting can not be + retrieved, defaults to ``None`` + + Returns: + - the ``value`` of the setting if exists or the value + specified in ``default`` + """ return self._settings.get(key, default) def set(self, key, value, value_type=None): + """Set a new value for a setting in the database. This + is only possible for settings defined in + ``app_settings.DYNAMICSETTINGS_INCLUDE_SETTINGS``. + If a setting is set to its original value it will not attempt to + save the "change" in the database (since its no real change). + + Params: + - ``key``: the name of the setting + - ``value``: new new value of the setting + - ``value_type`` (optional): tne new type of the value, if omitted it will + try to resolve the type from the value, should be a string + representing the (Python) type of the setting (for examome + 'int', 'str', 'list' ...) + + Returns: + - the new value of the setting + + Raises: + - ``KeyError`` if the setting can not be set or is not allowed + to set + """ if not value_type: value_type = type(value).__name__ if self.can_change(key): @@ -48,6 +89,18 @@ def set(self, key, value, value_type=None): raise KeyError('Setting "%s" can not be set in the database. If you want to change the setting add it to DYNAMICSETTINGS_INCLUDE_SETTINGS.' % key) def reset(self, key): + """Reset the value of a setting saved in the database. + Does not work for settings which are not saved in the database + of course. + + Params: + - ``key``: the name of the setting + + Returns: + - a boolean: ``True`` on success, ``False`` if the setting + could not be reset (either not allowed to reset or not saved + in the database) + """ if self.can_change(key): try: dynamic_setting = models.Settings.objects.get(key=key) @@ -58,6 +111,18 @@ def reset(self, key): return False def dict(self, keys=None): + """Returns a dict representation of the settings + where the key is the name of the setting and the value + is its value. + + Params: + - ``keys`` (optional): a list of setting names (as strings) + which should be included in the dict. If ommitted will show + all settings. + + Returns: + - a dict representing the settings + """ if keys is None: return self._settings new_dict = {} @@ -66,8 +131,14 @@ def dict(self, keys=None): return new_dict def is_in_db(self, key): - """ - Check if a setting for a given key is saved in the Database + """Check if a setting for a given key is saved in the Database + + Params: + - ``key``: the name of the setting + + Returns: + - a boolean: ``True`` if setting is saved in the database, + ``False`` otherwise """ try: models.Settings.objects.get(key=key) @@ -76,13 +147,21 @@ def is_in_db(self, key): return True def can_change(self, key): - """ + """Check if a setting for a given key can be changed in the Database + A setting can be change in the database if: a) its not in the global settings, but defined in the settings from DYNAMICSETTINGS_INCLUDE_MODULES OR b) its defined in DYNAMICSETTINGS_INCLUDE_SETTINGS, even it is in the global settings + + Params: + - ``key``: the name of the setting + + Returns: + - a boolean: ``True`` if setting can be changed in the database, + ``False`` otherwise """ try: setting_value = self.__getattr__(key) @@ -109,16 +188,6 @@ def _combine_settings(self): if settings_module is not None: settings_dict = self._filter_settings(settings_module) all_settings.update(settings_dict) - #third check for settings defined in DYNAMICSETTINGS_INCLUDE_SETTINGS - #and overwrite them - """ - for setting_name in app_settings.DYNAMICSETTINGS_INCLUDE_SETTINGS: - #try to get it from global settings (if its provided in DYNAMICSETTINGS_INCLUDE_MODULES - #it will be loaded already anyway - setting_value = None - settings_dict = {setting_name: django_settings.__getattr__(setting_name)} - all_settings.update(settings_dict) - """ #and finally check within the db db_settings_dict = {} db_settings = models.Settings.objects.all() @@ -151,3 +220,4 @@ def __getattr__(self, key): settings = LazyDynamicSettings() + diff --git a/dynamicsettings/app_settings.py b/dynamicsettings/app_settings.py index e821ac4..a6f0994 100644 --- a/dynamicsettings/app_settings.py +++ b/dynamicsettings/app_settings.py @@ -10,8 +10,11 @@ *Notes*: -- ``myapp.app_settings`` should be an available module in myapp (``myapp/app_settings.py``) somewhere in the project dir or PYTHONPATH -- ``some_globals`` should be an available module either in the project dir or somewhere in the PYTHONPATH: ``some_globals.py`` +- ``myapp.app_settings`` should be an available module in myapp + (``myapp/app_settings.py``) somewhere in the project dir or + PYTHONPATH +- ``some_globals`` should be an available module either in the + project dir or somewhere in the PYTHONPATH: ``some_globals.py`` **Note**: if a settings module provided in DYNAMICSETTINGS_INCLUDE_MODULES is not @@ -28,7 +31,8 @@ *Notes*: - ``MY_SETTING`` or ``DEFAULT_CACHE_DURATION`` should be an available setting name -either the global django settings or in the ones provided in DYNAMICSETTINGS_INCLUDE_MODULES + either the global django settings or in the ones provided in + DYNAMICSETTINGS_INCLUDE_MODULES **Note**: if a setting provided in DYNAMICSETTINGS_INCLUDE_SETTINGS is not available it will raise an exception. diff --git a/dynamicsettings/forms.py b/dynamicsettings/forms.py index d77546f..7a5ab65 100644 --- a/dynamicsettings/forms.py +++ b/dynamicsettings/forms.py @@ -10,6 +10,13 @@ from dynamicsettings import settings class SettingsForm(forms.ModelForm): + """Form class which helps to validate + a setting before it is saved in the database. + Have a closer look to the clean() method to + find out more about the details when a setting + is rejected to be saved + """ + class Meta: model = models.Settings @@ -35,7 +42,6 @@ def clean(self): 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) - d) Pickle the value """ error_message_tmpl = 'A setting from type %s must be set to %s.' key = self.cleaned_data['key'] diff --git a/dynamicsettings/views.py b/dynamicsettings/views.py index 7d1e4a8..023eda9 100644 --- a/dynamicsettings/views.py +++ b/dynamicsettings/views.py @@ -1,26 +1,5 @@ # -*- coding: utf-8 -*- -#for now in views - -""" - - - -**Why this is using _dynamicsettings_... "private" functions instead -of normal view functions?** - -Currenty (Django 1.3) there is a bug in the gehavior of django.test.client.Client -handling cookies and sessions: http://code.djangoproject.com/ticket/10899 and -http://code.djangoproject.com/ticket/15740. - -To use tests for this view which require a login (in this case via -staff_member_required decorator) are not working. Therefore to test -these views, they are written into non decorated functions which are -then called by the actual view function (with decorator). These undecorated -functions are used for tests instead of the normal view functions. See -dynamicsettings.tests.urls. -""" - from django import shortcuts from django import forms from django.utils import simplejson @@ -36,6 +15,23 @@ @staff_member_required 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 = [] @@ -63,8 +59,25 @@ def dynamicsettings_index(request): @staff_member_required def dynamicsettings_set(request): - """ - Handles the post request + """A view to handle the POST request to + set a setting in the database + + Params: + - ``request``: a django http request object + + Returns: + - a response as JSON including the following fields: + - ``status``: "success" if the setting was saved in + the database, "error" in other cases + - on success: + - ``value``: the new value of the setting (which is + saved in the database) + - ``type``: the new type of the setting, can only differ + from the original type if it was ``NoneType`` + - on error: + - ``message``: the message describing the error + - ``form``: the validated form rendered in a template + (will show the error in the form) """ if request.method=='POST': response_dict = {} @@ -95,6 +108,23 @@ def dynamicsettings_set(request): @staff_member_required def dynamicsettings_reset(request): + """A view to handle the POST request to + reset a setting in the database + + Params: + - ``request``: a django http request object + + Returns: + - a response as JSON including the following fields: + - ``status``: "success" if the setting was reset in + the database, "error" in other cases + - on success: + - ``value``: the original value of the setting (which is + not saved in the database) + - ``type``: the original type of the setting + - on error: + - ``message``: the message describing the error + """ if request.method=='POST': key = request.POST.get('key', None) if key is None: diff --git a/setup.py b/setup.py index dff0dac..62fc978 100644 --- a/setup.py +++ b/setup.py @@ -3,7 +3,7 @@ setup( name='django-dynamic-settings', version='0.1', - description='Application to handle settings within Django.', + description='Application to handle live settings within Django.', author='Sterno.Ru', author_email='sterno.beijing@gmail.com', url='',