Merge pull request #13 from BlindHunter/master

Merging pull request to enable per-model override of templates.
master
Brandon Taylor 2012-09-24 07:13:00 -07:00
commit d22307c8fb
8 changed files with 58 additions and 35 deletions

View File

@ -16,8 +16,16 @@ STATIC_URL = settings.STATIC_URL
class SortableAdmin(ModelAdmin): class SortableAdmin(ModelAdmin):
"""
"""
ordering = ('order', 'id') ordering = ('order', 'id')
sortable_change_list_with_sort_link_template = 'adminsortable/change_list_with_sort_link.html'
sortable_change_form_template = 'adminsortable/change_form.html'
sortable_change_list_template = 'adminsortable/change_list.html'
sortable_javascript_includes_template = 'adminsortable/shared/javascript_includes.html'
class Meta: class Meta:
abstract = True abstract = True
@ -47,9 +55,9 @@ class SortableAdmin(ModelAdmin):
admin_urls = patterns('', admin_urls = patterns('',
url(r'^sorting/do-sorting/(?P<model_type_id>\d+)/$', url(r'^sorting/do-sorting/(?P<model_type_id>\d+)/$',
self.admin_site.admin_view(self.do_sorting_view), self.admin_site.admin_view(self.do_sorting_view),
name='admin_do_sorting'), #this view changes the order name=('%s_do_sorting' % self.model._meta.app_label)), #this view changes the order
url(r'^sort/$', self.admin_site.admin_view(self.sort_view), url(r'^sort/$', self.admin_site.admin_view(self.sort_view),
name='admin_sort'), #this view shows a link to the drag-and-drop view name=('%s_sort' % self.model._meta.app_label)), #this view shows a link to the drag-and-drop view
) )
return admin_urls + urls return admin_urls + urls
@ -116,9 +124,10 @@ class SortableAdmin(ModelAdmin):
'group_expression' : sortable_by_expression, 'group_expression' : sortable_by_expression,
'sortable_by_class' : sortable_by_class, 'sortable_by_class' : sortable_by_class,
'sortable_by_class_is_sortable' : sortable_by_class_is_sortable, 'sortable_by_class_is_sortable' : sortable_by_class_is_sortable,
'sortable_by_class_display_name' : sortable_by_class_display_name 'sortable_by_class_display_name' : sortable_by_class_display_name,
'sortable_javascript_includes_template': self.sortable_javascript_includes_template
} }
return render(request, 'adminsortable/change_list.html', context) return render(request, self.sortable_change_list_template, context)
def changelist_view(self, request, extra_context=None): def changelist_view(self, request, extra_context=None):
""" """
@ -127,13 +136,14 @@ class SortableAdmin(ModelAdmin):
block to take people to the view to change the sorting. block to take people to the view to change the sorting.
""" """
if self.model.is_sortable(): if self.model.is_sortable():
self.change_list_template = 'adminsortable/change_list_with_sort_link.html' self.change_list_template = self.sortable_change_list_with_sort_link_template
return super(SortableAdmin, self).changelist_view(request, extra_context=extra_context) return super(SortableAdmin, self).changelist_view(request, extra_context=extra_context)
def change_view(self, request, object_id, extra_context=None): def change_view(self, request, object_id, extra_context=None):
if self.has_sortable_tabular_inlines or self.has_sortable_stacked_inlines: if self.has_sortable_tabular_inlines or self.has_sortable_stacked_inlines:
self.change_form_template = 'adminsortable/change_form.html' self.change_form_template = self.sortable_change_form_template
extra_context = { extra_context = {
'sortable_javascript_includes_template': self.sortable_javascript_includes_template,
'has_sortable_tabular_inlines' : self.has_sortable_tabular_inlines, 'has_sortable_tabular_inlines' : self.has_sortable_tabular_inlines,
'has_sortable_stacked_inlines' : self.has_sortable_stacked_inlines 'has_sortable_stacked_inlines' : self.has_sortable_stacked_inlines
} }
@ -164,14 +174,12 @@ class SortableAdmin(ModelAdmin):
setattr(obj, 'order', start_index) setattr(obj, 'order', start_index)
obj.save() obj.save()
start_index += step start_index += step
response = {'objects_sorted' : True} response = {'objects_sorted' : True}
except (Key, IndexError, klass.DoesNotExist, AttributeError): except (KeyError, IndexError, klass.DoesNotExist, AttributeError):
pass pass
else: else:
response = {'objects_sorted' : False} response = {'objects_sorted' : False}
return HttpResponse(json.dumps(response, ensure_ascii=False), return HttpResponse(json.dumps(response, ensure_ascii=False), mimetype='application/json')
mimetype='application/json')
class SortableInlineBase(InlineModelAdmin): class SortableInlineBase(InlineModelAdmin):

View File

@ -7,7 +7,7 @@
{% url 'admin:jsi18n' as jsi18nurl %} {% url 'admin:jsi18n' as jsi18nurl %}
{% if has_sortable_tabular_inlines or has_sortable_stacked_inlines %} {% if has_sortable_tabular_inlines or has_sortable_stacked_inlines %}
{% include 'adminsortable/shared/javascript_includes.html' %} {% include sortable_javascript_includes_template %}
{% endif %} {% endif %}
{% if has_sortable_tabular_inlines %} {% if has_sortable_tabular_inlines %}
<script type="text/javascript" src="{{ STATIC_URL }}adminsortable/js/admin.sortable.tabular.inlines.js"></script> <script type="text/javascript" src="{{ STATIC_URL }}adminsortable/js/admin.sortable.tabular.inlines.js"></script>

View File

@ -8,7 +8,7 @@
{% block extrahead %} {% block extrahead %}
{{ block.super }} {{ block.super }}
{% include 'adminsortable/shared/javascript_includes.html' %} {% include sortable_javascript_includes_template %}
{% endblock %} {% endblock %}
{% block breadcrumbs %} {% block breadcrumbs %}

View File

@ -1,4 +1,4 @@
{% load i18n adminmedia %} {% load i18n adminmedia adminsortable_tags %}
<div class="inline-group" id="{{ inline_admin_formset.formset.prefix }}-group"> <div class="inline-group" id="{{ inline_admin_formset.formset.prefix }}-group">
<h2>{{ inline_admin_formset.opts.verbose_name_plural|title }} {% if inline_admin_formset.opts.is_sortable %} - drag and drop to change order{% endif %}</h2> <h2>{{ inline_admin_formset.opts.verbose_name_plural|title }} {% if inline_admin_formset.opts.is_sortable %} - drag and drop to change order{% endif %}</h2>
{{ inline_admin_formset.formset.management_form }} {{ inline_admin_formset.formset.management_form }}
@ -17,7 +17,7 @@
{% if inline_admin_form.has_auto_field %}{{ inline_admin_form.pk_field.field }}{% endif %} {% if inline_admin_form.has_auto_field %}{{ inline_admin_form.pk_field.field }}{% endif %}
{{ inline_admin_form.fk_field.field }} {{ inline_admin_form.fk_field.field }}
{% if inline_admin_form.original %} {% if inline_admin_form.original %}
<input type="hidden" name="admin_sorting_url" value="{% url admin:admin_do_sorting inline_admin_form.original.model_type_id %}" /> <input type="hidden" name="admin_sorting_url" value="{% get_do_sorting_url inline_admin_form.original.model_type_id %}" />
{% endif %} {% endif %}
</div> </div>
{% endfor %} {% endfor %}

View File

@ -1,4 +1,4 @@
{% load i18n adminmedia admin_modify %} {% load i18n adminmedia admin_modify adminsortable_tags %}
<div class="inline-group" id="{{ inline_admin_formset.formset.prefix }}-group"> <div class="inline-group" id="{{ inline_admin_formset.formset.prefix }}-group">
<div class="tabular inline-related {% if forloop.last %}last-related{% endif %}"> <div class="tabular inline-related {% if forloop.last %}last-related{% endif %}">
{{ inline_admin_formset.formset.management_form }} {{ inline_admin_formset.formset.management_form }}
@ -40,7 +40,7 @@
{% endfor %} {% endfor %}
{% endspaceless %} {% endspaceless %}
{% if inline_admin_form.original %} {% if inline_admin_form.original %}
<input type="hidden" name="admin_sorting_url" value="{% url admin:admin_do_sorting inline_admin_form.original.model_type_id %}" /> <input type="hidden" name="admin_sorting_url" value="{% get_do_sorting_url inline_admin_form.original %}" />
{% endif %} {% endif %}
</td> </td>
{% for fieldset in inline_admin_form %} {% for fieldset in inline_admin_form %}

View File

@ -1,4 +1,6 @@
{% load adminsortable_tags %}
<form> <form>
<input name="pk" type="hidden" value="{{ object.pk }}" /> <input name="pk" type="hidden" value="{{ object.pk }}" />
</form> </form>
<a href="{% url admin:admin_do_sorting object.model_type_id %}" class="admin_sorting_url">{{ object }}</a> <a href="{% get_do_sorting_url object %}" class="admin_sorting_url">{{ object }}</a>

View File

@ -1,27 +1,40 @@
from django import template from django import template
from django.core.urlresolvers import reverse
register = template.Library() register = template.Library()
@register.inclusion_tag('adminsortable/shared/objects.html', takes_context=True) @register.simple_tag(takes_context=True)
def render_sortable_objects(context, objects): def render_sortable_objects(context, objects,
return {'objects' : objects} sortable_objects_template='adminsortable/shared/objects.html'):
context.update({'objects': objects})
tmpl = template.loader.get_template(sortable_objects_template)
return tmpl.render(context)
@register.inclusion_tag('adminsortable/shared/nested_objects.html', takes_context=True) @register.simple_tag(takes_context=True)
def render_nested_sortable_objects(context, objects, group_expression): def render_nested_sortable_objects(context, objects, group_expression,
group_expression = context.get('group_expression') sortable_nested_objects_template = 'adminsortable/shared/nested_objects.html'):
sortable_on_class = context.get('sortable_on_class') context.update({'objects': objects, 'group_expression': group_expression})
return {'objects' : objects, 'group_expression' : group_expression, tmpl = template.loader.get_template(sortable_nested_objects_template)
'sortable_on_class' : sortable_on_class, return tmpl.render(context)
'sortable_by_class_is_sortable' : context.get('sortable_by_class_is_sortable')}
@register.inclusion_tag('adminsortable/shared/list_items.html', takes_context=True) @register.simple_tag(takes_context=True)
def render_list_items(context, list_objects): def render_list_items(context, list_objects,
return {'list_objects' : list_objects} sortable_list_items_template='adminsortable/shared/list_items.html'):
context.update({'list_objects': list_objects})
tmpl = template.loader.get_template(sortable_list_items_template)
return tmpl.render(context)
@register.inclusion_tag('adminsortable/shared/object_rep.html', takes_context=True) @register.simple_tag(takes_context=True)
def render_object_rep(context, object): def render_object_rep(context, obj, sortable_object_rep_template='adminsortable/shared/object_rep.html'):
return {'object' : object} context.update({'object': obj})
tmpl = template.loader.get_template(sortable_object_rep_template)
return tmpl.render(context)
@register.simple_tag(takes_context=False)
def get_do_sorting_url(obj):
return reverse('admin:%s_do_sorting' % obj._meta.app_label, kwargs={'model_type_id': obj.model_type_id() })

View File

@ -79,7 +79,7 @@ class SortableTestCase(TestCase):
return category1, category2, category3 return category1, category2, category3
def get_sorting_url(self): def get_sorting_url(self):
return reverse('admin:admin_do_sorting', args=(), return reverse('admin:app_do_sorting', args=(),
kwargs={'model_type_id' : Category.model_type_id()}) kwargs={'model_type_id' : Category.model_type_id()})
def get_category_indexes(self, *categories): def get_category_indexes(self, *categories):
@ -89,7 +89,7 @@ class SortableTestCase(TestCase):
logged_in = self.client.login(username=self.user.username, password=self.user_raw_password) logged_in = self.client.login(username=self.user.username, password=self.user_raw_password)
self.assertTrue(logged_in, 'User is not logged in') self.assertTrue(logged_in, 'User is not logged in')
response = self.client.get(reverse('admin:admin_sort')) response = self.client.get(reverse('admin:app_sort'))
self.assertEqual(response.status_code, httplib.OK, u'Admin sort request failed.') self.assertEqual(response.status_code, httplib.OK, u'Admin sort request failed.')
#assert adminsortable change list templates are used #assert adminsortable change list templates are used