mirror of
https://github.com/encode/django-rest-framework.git
synced 2025-07-27 08:29:59 +03:00
made it compatible with the old ordering template and added rendering tests for them
This commit is contained in:
parent
226deb5707
commit
2883a0256a
|
@ -275,33 +275,39 @@ class OrderingFilter(BaseFilterBackend):
|
|||
return queryset
|
||||
|
||||
def get_template_context(self, request, queryset, view):
|
||||
current = self.get_ordering(request, queryset, view)
|
||||
if not current:
|
||||
current = None
|
||||
# current and options should be deleted with the next major update
|
||||
currents = self.get_ordering(request, queryset, view)
|
||||
current = None if not currents else currents[0]
|
||||
options = []
|
||||
options_plus = []
|
||||
context = {
|
||||
'request': request,
|
||||
'current': current,
|
||||
'currents': currents,
|
||||
'param': self.ordering_param,
|
||||
}
|
||||
for key, label in self.get_valid_fields(queryset, view, context):
|
||||
options.append((key, '%s - %s' % (label, _('ascending')), *self.plus_key(current, key)))
|
||||
options.append(('-' + key, '%s - %s' % (label, _('descending')), *self.plus_key(current, '-' + key)))
|
||||
for sign, order_label in [('', _('ascending')), ('-', _('descending'))]:
|
||||
item = (sign + key, '%s - %s' % (label, order_label))
|
||||
options.append(item)
|
||||
options_plus.append(item + self.plus_key(currents, sign + key))
|
||||
|
||||
context['options'] = options
|
||||
context['options_plus'] = options_plus
|
||||
return context
|
||||
|
||||
@staticmethod
|
||||
def plus_key(current, key):
|
||||
def plus_key(currents, key):
|
||||
priority = None
|
||||
plus_key = None
|
||||
if current:
|
||||
if len(current) > 1:
|
||||
if currents:
|
||||
if len(currents) > 1:
|
||||
try:
|
||||
priority = current.index(key) + 1
|
||||
priority = currents.index(key) + 1
|
||||
except ValueError:
|
||||
pass
|
||||
|
||||
for_plus = current.copy()
|
||||
for_plus = currents.copy()
|
||||
if key in for_plus:
|
||||
# for click on minus
|
||||
for_plus.remove(key)
|
||||
|
|
|
@ -87,4 +87,4 @@ pre {
|
|||
|
||||
#filtersModal .list-group-item:hover .glyphicon-plus[data-plus-ordering] {
|
||||
visibility: visible;
|
||||
}
|
||||
}
|
||||
|
|
|
@ -2,8 +2,8 @@
|
|||
{% load i18n %}
|
||||
<h2>{% trans "Ordering" %}</h2>
|
||||
<div class="list-group">
|
||||
{% for key, label, priority, plus_key in options %}
|
||||
{% if key in current %}
|
||||
{% for key, label, priority, plus_key in options_plus %}
|
||||
{% if key in currents %}
|
||||
<a href="{% add_query_param request param key %}" class="list-group-item active">
|
||||
<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>
|
||||
|
@ -14,7 +14,7 @@
|
|||
</a>
|
||||
{% else %}
|
||||
<a href="{% add_query_param request param key %}" class="list-group-item">
|
||||
{% if current %}
|
||||
{% if currents %}
|
||||
<span class="glyphicon glyphicon-plus" style="float: right" aria-hidden="true"
|
||||
data-plus-ordering="{% add_query_param request param plus_key %}"></span>
|
||||
{% endif %}
|
||||
|
|
|
@ -6,12 +6,15 @@ from django.core.exceptions import ImproperlyConfigured
|
|||
from django.db import models
|
||||
from django.db.models import CharField, Transform
|
||||
from django.db.models.functions import Concat, Upper
|
||||
from django.template import Context, Template
|
||||
from django.test import TestCase
|
||||
from django.test.utils import override_settings
|
||||
|
||||
from rest_framework import filters, generics, serializers
|
||||
from rest_framework.compat import coreschema
|
||||
from rest_framework.request import Request
|
||||
from rest_framework.test import APIRequestFactory
|
||||
from rest_framework.viewsets import ViewSet
|
||||
|
||||
factory = APIRequestFactory()
|
||||
|
||||
|
@ -712,43 +715,97 @@ class OrderingFilterTests(TestCase):
|
|||
view(request)
|
||||
|
||||
|
||||
class OrderingViewSet(ViewSet):
|
||||
ordering_fields = [
|
||||
('id', 'ID'),
|
||||
('slug', 'Slug'),
|
||||
('author', 'Author'),
|
||||
]
|
||||
|
||||
|
||||
oldOrderingTemplate = Template("""
|
||||
{% load rest_framework %}
|
||||
{% load i18n %}
|
||||
<h2>{% trans "Ordering" %}</h2>
|
||||
<div class="list-group">
|
||||
{% for key, label in options %}
|
||||
{% if key == 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 }}
|
||||
</a>
|
||||
{% else %}
|
||||
<a href="{% add_query_param request param key %}" class="list-group-item">{{ label }}</a>
|
||||
{% endif %}
|
||||
{% endfor %}
|
||||
</div>
|
||||
""")
|
||||
|
||||
|
||||
class OrderingFilterPlusGlyphTests(TestCase):
|
||||
def setUp(self):
|
||||
self.filter = filters.OrderingFilter()
|
||||
def create_objects(self, currents):
|
||||
self.ordering_filter = filters.OrderingFilter()
|
||||
self.request = Request(factory.get('/', {'ordering': ','.join(currents)} if currents else None))
|
||||
self.view = OrderingViewSet()
|
||||
|
||||
def assertPlusResult(self, currents, expected):
|
||||
self.create_objects(currents)
|
||||
|
||||
context = self.ordering_filter.get_template_context(self.request, None, self.view)
|
||||
for key, expected_prio_and_plus_key in expected.items():
|
||||
prio_and_plus_key = [x[2:] for x in context['options_plus'] if x[0] == key][0]
|
||||
self.assertEqual(prio_and_plus_key, expected_prio_and_plus_key)
|
||||
|
||||
self.assertOldTemplateWillRenderProperly(context)
|
||||
|
||||
def assertOldTemplateWillRenderProperly(self, context_dict):
|
||||
context = Context(context_dict)
|
||||
result = oldOrderingTemplate.render(context)
|
||||
|
||||
for key, label in context_dict['options']:
|
||||
self.assertIn('ordering=' + key, result)
|
||||
self.assertIn(label, result)
|
||||
|
||||
if context_dict['current']:
|
||||
self.assertIn('class="glyphicon glyphicon-ok"', result)
|
||||
|
||||
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'))
|
||||
current_ordering = None
|
||||
expected = {
|
||||
'id': (None, None),
|
||||
'-id': (None, None),
|
||||
}
|
||||
self.assertPlusResult(current_ordering, expected)
|
||||
|
||||
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'))
|
||||
def test_one_ordering_param(self):
|
||||
current_ordering = ['id']
|
||||
expected = {
|
||||
'id': (None, None),
|
||||
'-id': (None, '-id'),
|
||||
'slug': (None, 'id,slug'),
|
||||
'-slug': (None, 'id,-slug'),
|
||||
}
|
||||
self.assertPlusResult(current_ordering, expected)
|
||||
|
||||
self.assertEqual((None, '-id'), self.filter.plus_key(['id'], '-id'))
|
||||
self.assertEqual((None, 'id'), self.filter.plus_key(['-id'], 'id'))
|
||||
current_ordering = ['-id']
|
||||
expected = {
|
||||
'id': (None, 'id'),
|
||||
'-id': (None, None),
|
||||
'slug': (None, '-id,slug'),
|
||||
'-slug': (None, '-id,-slug'),
|
||||
}
|
||||
self.assertPlusResult(current_ordering, expected)
|
||||
|
||||
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'))
|
||||
def test_two_ordering_params(self):
|
||||
current_ordering = ['id', 'slug']
|
||||
expected = {
|
||||
'id': (1, 'slug'),
|
||||
'-id': (None, 'slug,-id'),
|
||||
'slug': (2, 'id'),
|
||||
'-slug': (None, 'id,-slug'),
|
||||
'author': (None, 'id,slug,author'),
|
||||
'-author': (None, 'id,slug,-author'),
|
||||
}
|
||||
self.assertPlusResult(current_ordering, expected)
|
||||
|
||||
|
||||
class SensitiveOrderingFilterModel(models.Model):
|
||||
|
|
Loading…
Reference in New Issue
Block a user