mirror of
https://github.com/encode/django-rest-framework.git
synced 2025-07-27 08:29:59 +03:00
Allow select additional sort criteria on modal filter form
This commit is contained in:
parent
883f6fe814
commit
226deb5707
|
@ -276,7 +276,8 @@ class OrderingFilter(BaseFilterBackend):
|
|||
|
||||
def get_template_context(self, request, queryset, view):
|
||||
current = self.get_ordering(request, queryset, view)
|
||||
current = None if not current else current[0]
|
||||
if not current:
|
||||
current = None
|
||||
options = []
|
||||
context = {
|
||||
'request': request,
|
||||
|
@ -284,11 +285,36 @@ class OrderingFilter(BaseFilterBackend):
|
|||
'param': self.ordering_param,
|
||||
}
|
||||
for key, label in self.get_valid_fields(queryset, view, context):
|
||||
options.append((key, '%s - %s' % (label, _('ascending'))))
|
||||
options.append(('-' + key, '%s - %s' % (label, _('descending'))))
|
||||
options.append((key, '%s - %s' % (label, _('ascending')), *self.plus_key(current, key)))
|
||||
options.append(('-' + key, '%s - %s' % (label, _('descending')), *self.plus_key(current, '-' + key)))
|
||||
context['options'] = options
|
||||
return context
|
||||
|
||||
@staticmethod
|
||||
def plus_key(current, key):
|
||||
priority = None
|
||||
plus_key = None
|
||||
if current:
|
||||
if len(current) > 1:
|
||||
try:
|
||||
priority = current.index(key) + 1
|
||||
except ValueError:
|
||||
pass
|
||||
|
||||
for_plus = current.copy()
|
||||
if key in for_plus:
|
||||
# for click on minus
|
||||
for_plus.remove(key)
|
||||
else:
|
||||
# for click on plus - rearrange sort priorities
|
||||
# remove key or -key
|
||||
for_plus = [k for k in for_plus if k.lstrip('-') != key.lstrip('-')]
|
||||
for_plus.append(key)
|
||||
if for_plus:
|
||||
plus_key = ','.join(for_plus)
|
||||
|
||||
return priority, plus_key
|
||||
|
||||
def to_html(self, request, queryset, view):
|
||||
template = loader.get_template(self.template)
|
||||
context = self.get_template_context(request, queryset, view)
|
||||
|
|
|
@ -80,3 +80,11 @@ pre {
|
|||
#filtersModal .modal-body h2 {
|
||||
margin-top: 0
|
||||
}
|
||||
|
||||
#filtersModal .list-group-item .glyphicon-plus[data-plus-ordering] {
|
||||
visibility: hidden;
|
||||
}
|
||||
|
||||
#filtersModal .list-group-item:hover .glyphicon-plus[data-plus-ordering] {
|
||||
visibility: visible;
|
||||
}
|
|
@ -41,6 +41,12 @@ $(document).ready(function() {
|
|||
$('.form-switcher a:first').tab('show');
|
||||
}
|
||||
|
||||
// add onclick to ordering plus and minus glyph
|
||||
$('#filtersModal span[data-plus-ordering]').click(function(e) {
|
||||
var glyph = $(e.target);
|
||||
glyph.closest('a.list-group-item').attr('href', glyph.attr('data-plus-ordering'));
|
||||
});
|
||||
|
||||
$(window).on('load', function() {
|
||||
$('#errorModal').modal('show');
|
||||
});
|
||||
|
|
|
@ -2,13 +2,24 @@
|
|||
{% load i18n %}
|
||||
<h2>{% trans "Ordering" %}</h2>
|
||||
<div class="list-group">
|
||||
{% for key, label in options %}
|
||||
{% if key == current %}
|
||||
{% for key, label, priority, plus_key in options %}
|
||||
{% if key in current %}
|
||||
<a href="{% add_query_param request param key %}" class="list-group-item active">
|
||||
<span class="glyphicon glyphicon-ok" style="float: right" aria-hidden="true"></span> {{ label }}
|
||||
<span class="glyphicon glyphicon-minus" style="float: right" aria-hidden="true"
|
||||
data-plus-ordering="{% if plus_key %}{% add_query_param request param plus_key %}{% else %}{% remove_query_param request param %}{% endif %}"></span>
|
||||
{% if priority %}
|
||||
<b style="float: right; display: inline-block; padding-right: 10px;">{{ priority }}</b>
|
||||
{% endif %}
|
||||
{{ label }}
|
||||
</a>
|
||||
{% else %}
|
||||
<a href="{% add_query_param request param key %}" class="list-group-item">{{ label }}</a>
|
||||
<a href="{% add_query_param request param key %}" class="list-group-item">
|
||||
{% if current %}
|
||||
<span class="glyphicon glyphicon-plus" style="float: right" aria-hidden="true"
|
||||
data-plus-ordering="{% add_query_param request param plus_key %}"></span>
|
||||
{% endif %}
|
||||
{{ label }}
|
||||
</a>
|
||||
{% endif %}
|
||||
{% endfor %}
|
||||
</div>
|
||||
|
|
|
@ -10,6 +10,7 @@ from django.utils.safestring import mark_safe
|
|||
|
||||
from rest_framework.compat import apply_markdown, pygments_highlight
|
||||
from rest_framework.renderers import HTMLFormRenderer
|
||||
from rest_framework.utils.urls import remove_query_param as _remove_query_param
|
||||
from rest_framework.utils.urls import replace_query_param
|
||||
|
||||
register = template.Library()
|
||||
|
@ -154,6 +155,16 @@ def add_query_param(request, key, val):
|
|||
return escape(replace_query_param(uri, key, val))
|
||||
|
||||
|
||||
@register.simple_tag
|
||||
def remove_query_param(request, key):
|
||||
"""
|
||||
Remove a query parameter from the current request url, and return the new url.
|
||||
"""
|
||||
iri = request.get_full_path()
|
||||
uri = iri_to_uri(iri)
|
||||
return escape(_remove_query_param(uri, key))
|
||||
|
||||
|
||||
@register.filter
|
||||
def as_string(value):
|
||||
if value is None:
|
||||
|
|
|
@ -712,6 +712,45 @@ class OrderingFilterTests(TestCase):
|
|||
view(request)
|
||||
|
||||
|
||||
class OrderingFilterPlusGlyphTests(TestCase):
|
||||
def setUp(self):
|
||||
self.filter = filters.OrderingFilter()
|
||||
|
||||
def test_no_ordering_defined(self):
|
||||
self.assertEqual((None, None), self.filter.plus_key(None, 'id'))
|
||||
self.assertEqual((None, None), self.filter.plus_key(None, '-id'))
|
||||
|
||||
def test_one_ordering_param_same_key(self):
|
||||
# there is no priority output at all
|
||||
self.assertEqual((None, None), self.filter.plus_key(['id'], 'id'))
|
||||
self.assertEqual((None, None), self.filter.plus_key(['-id'], '-id'))
|
||||
|
||||
self.assertEqual((None, '-id'), self.filter.plus_key(['id'], '-id'))
|
||||
self.assertEqual((None, 'id'), self.filter.plus_key(['-id'], 'id'))
|
||||
|
||||
def test_one_ordering_param_different_key(self):
|
||||
# there is no priority output at all
|
||||
self.assertEqual((None, 'id,slug'), self.filter.plus_key(['id'], 'slug'))
|
||||
self.assertEqual((None, 'id,-slug'), self.filter.plus_key(['id'], '-slug'))
|
||||
|
||||
self.assertEqual((None, '-id,slug'), self.filter.plus_key(['-id'], 'slug'))
|
||||
self.assertEqual((None, '-id,-slug'), self.filter.plus_key(['-id'], '-slug'))
|
||||
|
||||
def test_two_ordering_param_exist_key(self):
|
||||
self.assertEqual((1, 'slug'), self.filter.plus_key(['id', 'slug'], 'id'))
|
||||
self.assertEqual((None, 'slug,-id'), self.filter.plus_key(['id', 'slug'], '-id'))
|
||||
|
||||
self.assertEqual((2, 'id'), self.filter.plus_key(['id', 'slug'], 'slug'))
|
||||
self.assertEqual((None, 'id,-slug'), self.filter.plus_key(['id', 'slug'], '-slug'))
|
||||
|
||||
self.assertEqual((None, 'id,-slug'), self.filter.plus_key(['id', 'slug'], '-slug'))
|
||||
self.assertEqual((2, 'id'), self.filter.plus_key(['id', 'slug'], 'slug'))
|
||||
|
||||
def test_two_ordering_param_other_key(self):
|
||||
self.assertEqual((None, 'id,slug,author'), self.filter.plus_key(['id', 'slug'], 'author'))
|
||||
self.assertEqual((None, 'id,slug,-author'), self.filter.plus_key(['id', 'slug'], '-author'))
|
||||
|
||||
|
||||
class SensitiveOrderingFilterModel(models.Model):
|
||||
username = models.CharField(max_length=20)
|
||||
password = models.CharField(max_length=100)
|
||||
|
|
Loading…
Reference in New Issue
Block a user