1. David Jean Louis
  2. django-admin-tools

Commits

Alex Robbins  committed 413d287 Merge

Merged changes from izi.

  • Participants
  • Parent commits 896f04e, 3689d08
  • Branches default

Comments (0)

Files changed (20)

File CHANGELOG

View file
 django-admin-tools changelog
 ============================
 
+Version 0.2.0, 29 February 2010:
+--------------------------------
+
+* bookmarks are now being saved in the database (thanks @alexrobbins); 
+* dashboard preferences are also saved in the database;
+* added support for django-staticfiles STATIC_URL settings (thanks @dstufft);
+* added polish, italian, greek and brazilian locales;
+* updated docs.
+
+Backwards incompatible changes in 0.2.0
+~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
+Now, django-admin-tools stores menu and dashboard preferences in the database, 
+so you'll need to run syncdb and to add the django-admin-tools urls to your 
+urlconf. These steps are described in details in the documentation.
+You'll also need to add ``admin_tools`` to your ``INSTALLED_APPS`` for the 
+locales to work (this was not documented in previous versions).
+
+
 Version 0.1.2, 13 February 2010:
 --------------------------------
 
 * added a "bookmarks" menu item and the code to manage bookmarks;
 * fixed jquery issues with django 1.2.
 
+
 Version 0.1.1, 10 February 2010:
 --------------------------------
 

File admin_tools/dashboard/forms.py

View file
+from django import forms
+
+from admin_tools.dashboard.models import DashboardPreferences
+
+
+class DashboardPreferencesForm(forms.ModelForm):
+    """
+    This form allows the user to edit dashboard preferences. It doesn't show
+    the user field. It expects the user to be passed in from the view.
+    """
+
+    def __init__(self, user, *args, **kwargs):
+        super(DashboardPreferencesForm, self).__init__(*args, **kwargs)
+        self.user = user
+
+    def save(self, *args, **kwargs):
+        preferences = super(DashboardPreferencesForm, self).save(
+            commit=False,
+            *args,
+            **kwargs
+        )
+        preferences.user = self.user
+        preferences.save()
+        return preferences
+
+    class Meta:
+        fields = ('data',)
+        model = DashboardPreferences

File admin_tools/dashboard/models.py

View file
 This module contains the base classes for the dashboard and dashboard modules.
 """
 
+from django.db import models
 from django.contrib import admin
 from django.contrib.contenttypes.models import ContentType
 from django.core.urlresolvers import reverse
 from admin_tools.utils import AppListElementMixin
 
 
+class DashboardPreferences(models.Model):
+    """
+    This model represents the dashboard preferences for a user.
+    """
+    user = models.ForeignKey('auth.User')
+    data = models.TextField()
+
+    def __unicode__(self):
+        return "%s dashboard preferences" % self.user.username
+
+    class Meta:
+        db_table = 'admin_tools_dashboard_preferences'
+        ordering = ('user',)
+    
+
 class Dashboard(object):
     """
     Base class for dashboards.

File admin_tools/dashboard/templates/dashboard/dashboard.html

View file
 <script type="text/javascript">
 // <![CDATA[
 jQuery(function($) {
-    $('#{{ dashboard.get_id }}').dashboard({
-        'columns': {{ dashboard.columns }}
-    });
+    jQuery.getJSON(
+        '{% url admin-tools-dashboard-get-preferences %}',
+        function(data) {
+            $('#{{ dashboard.get_id }}').dashboard({
+                'columns': {{ dashboard.columns }},
+                'load_preferences_function': function(options) {
+                    return data;
+                },
+                'save_preferences_function': function(options, preferences) {
+                    jQuery.post(
+                        '{% url admin-tools-dashboard-set-preferences %}',
+                        { data: JSON.stringify(preferences) }
+                    );
+                }
+            });
+         }
+    );
 });
 //]]>
 </script>

File admin_tools/dashboard/templates/dashboard/preferences_form.html

View file
+{% extends "admin/base_site.html" %}
+
+{% block content %}
+
+<form action="." method="POST">
+    {{ form.as_p }}
+    <p><input type="submit" value="Save" /></p>
+</form>
+
+{% endblock %}

File admin_tools/dashboard/templatetags/admin_tools_dashboard_tags.py

View file
 import math
 from django import template
 from django.conf import settings
+from admin_tools.utils import get_media_url
 from admin_tools.dashboard.utils import get_dashboard
 
 register = template.Library()
         'template': dashboard.template,
         'dashboard': dashboard,
         'split_at': math.ceil(float(len(dashboard.children))/float(dashboard.columns)),
-        'media_url': settings.MEDIA_URL.rstrip('/'),
+        'media_url': get_media_url(),
         'has_disabled_modules': len([m for m in dashboard.children \
                                 if not m.enabled]) > 0,
     })
     context.update({
         'template' : 'dashboard/css.html',
         'css_files': dashboard.Media.css,
-        'media_url': settings.MEDIA_URL.rstrip('/'),
+        'media_url': get_media_url(),
     })
     return context
 admin_tools_render_dashboard_css = tag_func(admin_tools_render_dashboard_css)

File admin_tools/dashboard/urls.py

View file
+from django.conf.urls.defaults import *
+
+urlpatterns = patterns('admin_tools.dashboard.views',
+    url(r'^get_preferences/$', 'get_preferences', name='admin-tools-dashboard-get-preferences'),
+    url(r'^set_preferences/$', 'set_preferences', name='admin-tools-dashboard-set-preferences'),
+)

File admin_tools/dashboard/views.py

View file
-# Create your views here.
+from django.contrib.auth.decorators import login_required
+from django.http import HttpResponse, HttpResponseRedirect
+from django.shortcuts import get_object_or_404
+from django.utils import simplejson
+from django.views.generic.simple import direct_to_template
+
+try:
+    from django.views.decorators import csrf_exempt
+except ImportError:
+    from django.contrib.csrf.middleware import csrf_exempt
+
+from forms import DashboardPreferencesForm
+from models import DashboardPreferences
+
+
+@login_required
+@csrf_exempt
+def set_preferences(request):
+    """
+    This view serves and validates a preferences form.
+    """
+    try:
+        preferences = DashboardPreferences.objects.get(user=request.user)
+    except DashboardPreferences.DoesNotExist:
+        preferences = None
+    if request.method == "POST":
+        form = DashboardPreferencesForm(
+            user=request.user,
+            data=request.POST,
+            instance=preferences
+        )
+        if form.is_valid():
+            preferences = form.save()
+            if request.is_ajax():
+                return HttpResponse('true')
+            request.user.message_set.create(message='Preferences saved')
+        elif request.is_ajax():
+            return HttpResponse('false')
+    else:
+        form = DashboardPreferencesForm(user=request.user, instance=preferences)
+    return direct_to_template(request, 'dashboard/preferences_form.html', {
+        'form': form,   
+    })
+
+
+@login_required
+@csrf_exempt
+def get_preferences(request):
+    """
+    Returns the dashboard preferences for the current user in json format.
+    If no preferences are found, the return value is an empty json object.
+    """
+    try:
+        preferences = DashboardPreferences.objects.get(user=request.user)
+        data = preferences.data
+    except DashboardPreferences.DoesNotExist:
+        data = '{}'
+    return HttpResponse(data, mimetype='application/json')
+

File admin_tools/locale/pt_BR/LC_MESSAGES/django.mo

Binary file modified.

File admin_tools/locale/pt_BR/LC_MESSAGES/django.po

View file
 
 #: dashboard/models.py:85 menu/models.py:328
 msgid "Dashboard"
-msgstr ""
+msgstr "Painel de controle"
 
 #: dashboard/models.py:404
 msgid "Links"
-msgstr ""
+msgstr "Links"
 
 #: dashboard/models.py:460 dashboard/models.py:765 menu/models.py:333
 msgid "Applications"
-msgstr ""
+msgstr "Aplicativos"
 
 #: dashboard/models.py:603 dashboard/models.py:777 dashboard/models.py:836
 msgid "Recent Actions"
-msgstr ""
+msgstr "Ações recentes"
 
 #: dashboard/models.py:648
 msgid "No recent actions."
-msgstr ""
+msgstr "Nenhuma ação recente"
 
 #: dashboard/models.py:693
 msgid "RSS Feed"
-msgstr ""
+msgstr "RSS Feed"
 
 #: dashboard/models.py:742
 msgid "Quick links"
-msgstr ""
+msgstr "Links rápidos"
 
 #: dashboard/models.py:749
 msgid "Return to site"
-msgstr ""
+msgstr "Voltar"
 
 #: dashboard/models.py:753 theming/templates/admin/base.html:42
 msgid "Change password"
-msgstr ""
+msgstr "Trocar a senha"
 
 #: dashboard/models.py:757 theming/templates/admin/base.html:49
 msgid "Log out"
-msgstr ""
+msgstr "Sair"
 
 #: dashboard/models.py:771 menu/models.py:337
 msgid "Administration"
-msgstr ""
+msgstr "Administração"
 
 #: dashboard/models.py:783
 msgid "Latest Django News"
-msgstr ""
+msgstr "Últimas novidades do Django"
 
 #: dashboard/models.py:790
 msgid "Support"
-msgstr ""
+msgstr "Suporte"
 
 #: dashboard/models.py:793
 msgid "Django documentation"
-msgstr ""
+msgstr "Documentação do Django"
 
 #: dashboard/models.py:798
 msgid "Django \"django-users\" mailing list"
-msgstr ""
+msgstr "Mailing list do Django \"django-users\""
 
 #: dashboard/models.py:803
 msgid "Django irc channel"
-msgstr ""
+msgstr "Canal irc do Django"
 
 #: dashboard/templates/admin/app_index.html:9
 #: theming/templates/admin/base.html:56
 msgid "Home"
-msgstr ""
+msgstr "Início"
 
 #: dashboard/templates/admin/app_index.html:11
 #, python-format
 
 #: dashboard/templates/dashboard/dashboard.html:51
 msgid "Modules"
-msgstr ""
+msgstr "Módulos"
 
 #: dashboard/templates/dashboard/modules/app_list.html:13
 #: dashboard/templates/dashboard/modules/model_list.html:11
 msgid "Add"
-msgstr ""
+msgstr "Adicionar"
 
 #: dashboard/templates/dashboard/modules/app_list.html:14
 #: dashboard/templates/dashboard/modules/model_list.html:12
 msgid "Change"
-msgstr ""
+msgstr "Editar"
 
 #: menu/models.py:287
 msgid "Bookmarks"
-msgstr ""
+msgstr "Marcações"
 
 #: menu/templates/admin/base_site.html:3
 msgid "Django site admin"
-msgstr ""
+msgstr "Administração do site"
 
 #: menu/templates/admin/base_site.html:11
 msgid "Django administration"
-msgstr ""
+msgstr "Administração do Django"
 
 #: menu/templates/menu/menu.html:38
 msgid "Please enter a name for the bookmark"
-msgstr ""
+msgstr "Por favor, coloque um nome para a marcação"
 
 #: menu/templates/menu/menu.html:41
 msgid "Bookmark this page"
-msgstr ""
+msgstr "Marcar esta página"
 
 #: theming/templates/admin/base.html:29
 msgid "Welcome,"
-msgstr ""
+msgstr "Bem vindo"
 
 #: theming/templates/admin/base.html:34
 msgid "Documentation"
-msgstr ""
+msgstr "Documentação"

File admin_tools/media/admin_tools/js/jquery/jquery.dashboard.js

View file
                 panel_id: 'dashboard-panel',
                 dashboard_id: this.attr('id'),
                 dashboard_module_class: 'dashboard-module',
-                columns: 2
+                columns: 2,
+                load_preferences_function: false,
+                save_preferences_function: false
             }    
             var options = $.extend(defaults, options);
 
     });
 
     var preferences = false;
-    var cookie_name = false;
 
     var _initialize = function(elt, options) {
-        if (cookie_name === false) {
-            cookie_name = 'admin-tools.' + options.dashboard_id;
-        }
+        // load preferences
         if (preferences === false) {
-            var json_str = $.cookie(cookie_name);
-            preferences = json_str ? JSON.parse(json_str) : {};
+            if (options.load_preferences_function) {
+                preferences = options.load_preferences_function(options);
+            } else {
+                var json_str = $.cookie('admin-tools.' + options.dashboard_id);
+                preferences = json_str ? JSON.parse(json_str) : {};
+            }
         }
         // set ids if not set
         elt.children('div[id!=' + options.panel_id +']').each(function(index) {
     var _restore_positions = function(elt, options) {
         // restore positions
         try {
-            var saved_positions = _get_preference('positions');
+            var saved_positions = _get_preference(options, 'positions');
         } catch (e) {
             return;
         }
     var _columnize = function(elt, options) {
         var elts = elt.children('div[id!=' + options.panel_id +']');
         var size = Math.ceil(elts.length / options.columns);
-        var sizes = _get_preference('columns');
+        var sizes = _get_preference(options, 'columns');
         var percent = Math.floor(100 / options.columns);
         var start = 0;
         var stop = 0;
         elt.children().children('.disabled').each(function() {
             _delete_element($(this), options);
         });
-        if (preferences['disabled']) {
-            $.each(preferences['disabled'], function(k, v) {
+        if (_get_preference(options, 'disabled')) {
+            $.each(_get_preference(options, 'disabled'), function(k, v) {
                 v ? _delete_element($('#'+k), options) : _add_element($('#'+k), options);
             });
         }
-        if (preferences['collapsed']) {
-            $.each(preferences['collapsed'], function(k, v) {
+        if (_get_preference(options, 'collapsed')) {
+            $.each(_get_preference(options, 'collapsed'), function(k, v) {
                 if (v) {
                     _toggle_element($('#'+k), options);
                 }
             cursor: 'crosshair',
             opacity: 0.7,
             update: function() {
-                _set_preference('positions', false, _get_positions(elt, options));
+                _set_preference(options, 'positions', false, _get_positions(elt, options));
                 var columns = [];
                 elt.children('.dashboard-column').each(function() {
                     columns.push($(this).children().length);
                 });
-                _set_preference('columns', false, columns);
+                _set_preference(options, 'columns', false, columns, true);
             }
         });
     };
         elt.find('h2 a.toggle-icon').toggleClass('collapsed');
         elt.children('div').slideToggle();
         if (save_preference) {
-            _set_preference('collapsed', elt.attr('id'), elt.find('h2 a.toggle-icon').hasClass('collapsed'));
+            _set_preference(options, 'collapsed', elt.attr('id'), elt.find('h2 a.toggle-icon').hasClass('collapsed'), true);
         }
     };
 
         elt.fadeOut('fast');
         $('#' + options.panel_id).show();
         if (save_preference) {
-            _set_preference('disabled', elt.attr('id'), true);
+            _set_preference(options, 'disabled', elt.attr('id'), true, true);
         }
     };
 
         elt.removeClass('disabled');
         elt.fadeIn('fast');
         if (save_preference) {
-            _set_preference('disabled', elt.attr('id'), false);
+            _set_preference(options, 'disabled', elt.attr('id'), false, true);
         }
         // if there's no element in the panel, hide it
         if (!$('#' + options.panel_id).find('li').length) {
         }
     };
 
-    var _get_preference = function(cat, id, defaultval) {
+    var load_preferences = function(options) {
+        if (options.load_preferences_function) {
+            return options.load_preferences_function(options);
+        }
+        if (preferences === false) {
+            var json_str = $.cookie('admin-tools.' + options.dashboard_id);
+            preferences = json_str ? JSON.parse(json_str) : {};
+        }
+        return preferences;
+    }
+
+    var _get_preference = function(options, cat, id, defaultval) {
         try {
             if (preferences[cat] == undefined) {
                 preferences[cat] = {};
         }
     };
 
-    var _set_preference = function(cat, id, val) {
+    // quick hack to ensure that we do not save preferences if they are 
+    // not modified...
+    var last_saved_preferences = null;
+
+    var _set_preference = function(options, cat, id, val, save) {
         try {
             if (preferences[cat] == undefined) {
                 preferences[cat] = {};
             }
         } catch (e) {
         }
-        $.cookie(cookie_name, JSON.stringify(preferences), {expires: 1825});
+        // save preferences
+        if (save && JSON.stringify(preferences) != last_saved_preferences) {
+            if (options.save_preferences_function) {
+                options.save_preferences_function(options, preferences);
+            } else {
+                $.cookie(cookie_name, JSON.stringify(preferences), {expires: 1825});
+            }
+            last_saved_preferences = JSON.stringify(preferences);
+        }
     };
 
     var _get_positions = function(elt, options) {

File admin_tools/menu/templates/menu/add_bookmark_form.html

View file
-<form id="bookmark-form" action="{% url add-bookmark %}" method="POST">
+<form id="bookmark-form" action="{% url admin-tools-menu-add-bookmark %}" method="POST">
     <input type="hidden" name="next" value="{% firstof url request.get_full_path|urlencode %}" />
     <input type="hidden" name="url" value="{% firstof url request.get_full_path|urlencode %}" />
     <input type="hidden" name="title" value="{{ title }}" />

File admin_tools/menu/templates/menu/remove_bookmark_form.html

View file
-<form id="bookmark-form" action="{% url remove-bookmark bookmark.id %}" method="POST">
+<form id="bookmark-form" action="{% url admin-tools-menu-remove-bookmark bookmark.id %}" method="POST">
     <input type="hidden" name="next" value="{% firstof url request.get_full_path|urlencode %}" />
     <button id="bookmark-button" class="bookmarked" type="submit">Remove</button>
 </form>

File admin_tools/menu/templatetags/admin_tools_menu_tags.py

View file
 from django import template
 from django.conf import settings
 from django.http import HttpRequest
+from admin_tools.utils import get_media_url
 from admin_tools.menu.models import Bookmark, BookmarkMenuItem
 from admin_tools.menu.utils import get_admin_menu
 
     context.update({
         'template': menu.template,
         'menu': menu,
-        'media_url': settings.MEDIA_URL.rstrip('/'),
+        'media_url': get_media_url(),
         'has_bookmark_item': has_bookmark_item,
         'bookmark': bookmark,
     })
     context.update({
         'template': 'menu/css.html',
         'css_files': menu.Media.css,
-        'media_url': settings.MEDIA_URL.rstrip('/'),
+        'media_url': get_media_url(),
     })
     return context
 admin_tools_render_menu_css = tag_func(admin_tools_render_menu_css)

File admin_tools/menu/urls.py

View file
 from django.conf.urls.defaults import *
 
 urlpatterns = patterns('admin_tools.menu.views',
-    url(r'^add_bookmark/$', 'add_bookmark', name='add-bookmark'),
-    url(r'^edit_bookmark/(?P<id>.+)/$', 'edit_bookmark', name='edit-bookmark'),
-    url(r'^remove_bookmark/(?P<id>.+)/$', 'remove_bookmark', name='remove-bookmark'),
+    url(r'^add_bookmark/$', 'add_bookmark', name='admin-tools-menu-add-bookmark'),
+    url(r'^edit_bookmark/(?P<id>.+)/$', 'edit_bookmark', name='admin-tools-menu-edit-bookmark'),
+    url(r'^remove_bookmark/(?P<id>.+)/$', 'remove_bookmark', name='admin-tools-menu-remove-bookmark'),
 )

File admin_tools/theming/templatetags/theming_tags.py

View file
 import os.path
 from django import template
 from django.conf import settings
+from admin_tools.utils import get_media_url
 
 register = template.Library()
 
     """
     css = getattr(settings, 'ADMIN_TOOLS_THEMING_CSS', False)
     if css:
-        css = os.path.join(settings.MEDIA_URL, css)
+        css = os.path.join(get_media_url(), css)
     else:
-        css = os.path.join(
-            getattr(settings, 'ADMIN_TOOLS_MEDIA_URL', settings.MEDIA_URL),
-            'admin_tools',
-            'css',
-            'theming.css'
-        )
+        css = os.path.join(get_media_url(), 'admin_tools', 'css', 'theming.css')
     return '<link rel="stylesheet" type="text/css" media="screen" href="%s" />' % css
 register.simple_tag(render_theming_css)

File admin_tools/urls.py

View file
 
 urlpatterns = patterns('',
     url(r'^menu/', include('admin_tools.menu.urls')),
+    url(r'^dashboard/', include('admin_tools.dashboard.urls')),
 )

File admin_tools/utils.py

View file
     def _get_admin_add_url(self, model):
         app_label = model._meta.app_label
         return reverse('admin:%s_%s_add' % (app_label, model.__name__.lower()))
+
+
+def get_media_url():
+    """
+    Returns the django admin tools media URL.
+    """
+    return getattr(
+        settings,
+        'ADMIN_TOOLS_MEDIA_URL',
+        getattr(settings, 'STATIC_URL', settings.MEDIA_URL)
+    ).rstrip('/')

File docs/configuration.rst

View file
   
       cp -r /usr/local/lib/python2.6/dist-packages/admin_tools/media/admin_tools /path/to/yourproject/media/
 
+django-admin-tools will look for the media directory in the following 
+settings variables (and in this order):
+
+* ``ADMIN_TOOLS_MEDIA_URL``;
+* ``STATIC_URL``: use this if you are using django-staticfiles;
+* ``MEDIA_URL``.
+
+
+Here's an example config if you are using django development server:
+
+``urls.py``::
+
+    (r'^site_media/(?P<path>.*)$', 'django.views.static.serve',
+        {'document_root': '/path/to/media'}),
+
+``settings.py``::
+
+    MEDIA_URL = '/site_media/'
+
+
 Available settings variables
 ----------------------------
 
+``ADMIN_TOOLS_MEDIA_URL``
+    You can use this variable if you want to set the media url for 
+    django-admin-tools to something different from your ``MEDIA_URL``.
+
 ``ADMIN_TOOLS_MENU``
     The path to your custom menu class, for example 
     "yourproject.menu.CustomMenu".

File docs/quickstart.rst

View file
         'django.core.context_processors.request',
     )
 
-Then, add the django-admin-tools modules to the ``INSTALLED_APPS`` like 
+Then, add admin_tools and its modules to the ``INSTALLED_APPS`` like 
 this::
 
     INSTALLED_APPS = (
+        'admin_tools',
         'admin_tools.theming',
         'admin_tools.menu',
         'admin_tools.dashboard',
     otherwise.
 
 django-admin-tools is modular, so if you want to disable a particular 
-module, just remove or comment it out in your ``INSTALLED_APPS``. 
+module, just remove or comment it out in your ``INSTALLED_APPS``, note 
+that ``admin_tools`` is required for i18n.
 
 
 Setting up the database