Closes #8995: Enable arbitrary ordering of REST API results

This commit is contained in:
jeremystretch 2022-04-08 16:00:33 -04:00
parent 9b8de19fe6
commit 03535ce50b
4 changed files with 87 additions and 1 deletions

View File

@ -0,0 +1,7 @@
# NetBox v3.3
## v3.3.0 (FUTURE)
### Enhancements
* [#8995](https://github.com/netbox-community/netbox/issues/8995) - Enable arbitrary ordering of REST API results

View File

@ -106,3 +106,23 @@ expression: `n`. Here is an example of a lookup expression on a foreign key, it
```no-highlight
GET /api/ipam/vlans/?group_id__n=3203
```
## Ordering Objects
To order results by a particular field, include the `ordering` query parameter. For example, order the list of sites according to their facility values:
```no-highlight
GET /api/dcim/sites/?ordering=facility
```
To invert the ordering, prepend a hyphen to the field name:
```no-highlight
GET /api/dcim/sites/?ordering=-facility
```
Multiple fields can be specified by separating the field names with a comma. For example:
```no-highlight
GET /api/dcim/sites/?ordering=facility,-name
```

View File

@ -26,7 +26,7 @@ django.utils.encoding.force_text = force_str
# Environment setup
#
VERSION = '3.2.1-dev'
VERSION = '3.3.0-dev'
# Hostname
HOSTNAME = platform.node()
@ -469,6 +469,7 @@ REST_FRAMEWORK = {
),
'DEFAULT_FILTER_BACKENDS': (
'django_filters.rest_framework.DjangoFilterBackend',
'rest_framework.filters.OrderingFilter',
),
'DEFAULT_METADATA_CLASS': 'netbox.api.metadata.BulkOperationMetadata',
'DEFAULT_PAGINATION_CLASS': 'netbox.api.pagination.OptionalLimitOffsetPagination',

View File

@ -176,6 +176,64 @@ class APIPaginationTestCase(APITestCase):
self.assertEqual(len(response.data['results']), 100)
class APIOrderingTestCase(APITestCase):
user_permissions = ('dcim.view_site',)
@classmethod
def setUpTestData(cls):
cls.url = reverse('dcim-api:site-list')
sites = (
Site(name='Site 1', slug='site-1', facility='C', description='Z'),
Site(name='Site 2', slug='site-2', facility='C', description='Y'),
Site(name='Site 3', slug='site-3', facility='B', description='X'),
Site(name='Site 4', slug='site-4', facility='B', description='W'),
Site(name='Site 5', slug='site-5', facility='A', description='V'),
Site(name='Site 6', slug='site-6', facility='A', description='U'),
)
Site.objects.bulk_create(sites)
def test_default_order(self):
response = self.client.get(self.url, format='json', **self.header)
self.assertHttpStatus(response, status.HTTP_200_OK)
self.assertEqual(response.data['count'], 6)
self.assertListEqual(
[s['name'] for s in response.data['results']],
['Site 1', 'Site 2', 'Site 3', 'Site 4', 'Site 5', 'Site 6']
)
def test_order_single_field(self):
response = self.client.get(f'{self.url}?ordering=description', format='json', **self.header)
self.assertHttpStatus(response, status.HTTP_200_OK)
self.assertEqual(response.data['count'], 6)
self.assertListEqual(
[s['name'] for s in response.data['results']],
['Site 6', 'Site 5', 'Site 4', 'Site 3', 'Site 2', 'Site 1']
)
def test_order_reversed(self):
response = self.client.get(f'{self.url}?ordering=-name', format='json', **self.header)
self.assertHttpStatus(response, status.HTTP_200_OK)
self.assertEqual(response.data['count'], 6)
self.assertListEqual(
[s['name'] for s in response.data['results']],
['Site 6', 'Site 5', 'Site 4', 'Site 3', 'Site 2', 'Site 1']
)
def test_order_multiple_fields(self):
response = self.client.get(f'{self.url}?ordering=facility,name', format='json', **self.header)
self.assertHttpStatus(response, status.HTTP_200_OK)
self.assertEqual(response.data['count'], 6)
self.assertListEqual(
[s['name'] for s in response.data['results']],
['Site 5', 'Site 6', 'Site 3', 'Site 4', 'Site 1', 'Site 2']
)
class APIDocsTestCase(TestCase):
def setUp(self):