mirror of
				https://github.com/encode/django-rest-framework.git
				synced 2025-11-04 01:47:59 +03:00 
			
		
		
		
	
							parent
							
								
									ef94861c2d
								
							
						
					
					
						commit
						2353878951
					
				| 
						 | 
				
			
			@ -264,13 +264,17 @@ For example:
 | 
			
		|||
 | 
			
		||||
    search_fields = ('=username', '=email')
 | 
			
		||||
 | 
			
		||||
By default, the search parameter is named `'search`', but this may be overridden with the `SEARCH_PARAM` setting.
 | 
			
		||||
 | 
			
		||||
For more details, see the [Django documentation][search-django-admin].
 | 
			
		||||
 | 
			
		||||
---
 | 
			
		||||
 | 
			
		||||
## OrderingFilter
 | 
			
		||||
 | 
			
		||||
The `OrderingFilter` class supports simple query parameter controlled ordering of results.  To specify the result order, set a query parameter named `'ordering'` to the required field name.  For example:
 | 
			
		||||
The `OrderingFilter` class supports simple query parameter controlled ordering of results.  By default, the query parameter is named `'ordering'`, but this may by overridden with the `ORDERING_PARAM` setting.
 | 
			
		||||
 | 
			
		||||
For example, to order users by username:
 | 
			
		||||
 | 
			
		||||
    http://example.com/api/users?ordering=username
 | 
			
		||||
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
| 
						 | 
				
			
			@ -158,6 +158,18 @@ A client request like the following would return a paginated list of up to 100 i
 | 
			
		|||
 | 
			
		||||
Default: `None`
 | 
			
		||||
 | 
			
		||||
### SEARCH_PARAM
 | 
			
		||||
 | 
			
		||||
The name of a query paramater, which can be used to specify the search term used by `SearchFilter`.
 | 
			
		||||
 | 
			
		||||
Default: `search`
 | 
			
		||||
 | 
			
		||||
#### ORDERING_PARAM
 | 
			
		||||
 | 
			
		||||
The name of a query paramater, which can be used to specify the ordering of results returned by `OrderingFilter`.
 | 
			
		||||
 | 
			
		||||
Default: `ordering`
 | 
			
		||||
 | 
			
		||||
---
 | 
			
		||||
 | 
			
		||||
## Authentication settings
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
| 
						 | 
				
			
			@ -6,6 +6,7 @@ from __future__ import unicode_literals
 | 
			
		|||
from django.core.exceptions import ImproperlyConfigured
 | 
			
		||||
from django.db import models
 | 
			
		||||
from rest_framework.compat import django_filters, six, guardian, get_model_name
 | 
			
		||||
from rest_framework.settings import api_settings
 | 
			
		||||
from functools import reduce
 | 
			
		||||
import operator
 | 
			
		||||
 | 
			
		||||
| 
						 | 
				
			
			@ -69,7 +70,8 @@ class DjangoFilterBackend(BaseFilterBackend):
 | 
			
		|||
 | 
			
		||||
 | 
			
		||||
class SearchFilter(BaseFilterBackend):
 | 
			
		||||
    search_param = 'search'  # The URL query parameter used for the search.
 | 
			
		||||
    # The URL query parameter used for the search.
 | 
			
		||||
    search_param = api_settings.SEARCH_PARAM
 | 
			
		||||
 | 
			
		||||
    def get_search_terms(self, request):
 | 
			
		||||
        """
 | 
			
		||||
| 
						 | 
				
			
			@ -107,7 +109,8 @@ class SearchFilter(BaseFilterBackend):
 | 
			
		|||
 | 
			
		||||
 | 
			
		||||
class OrderingFilter(BaseFilterBackend):
 | 
			
		||||
    ordering_param = 'ordering'  # The URL query parameter used for the ordering.
 | 
			
		||||
    # The URL query parameter used for the ordering.
 | 
			
		||||
    ordering_param = api_settings.ORDERING_PARAM
 | 
			
		||||
    ordering_fields = None
 | 
			
		||||
 | 
			
		||||
    def get_ordering(self, request):
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
| 
						 | 
				
			
			@ -69,6 +69,10 @@ DEFAULTS = {
 | 
			
		|||
    'PAGINATE_BY_PARAM': None,
 | 
			
		||||
    'MAX_PAGINATE_BY': None,
 | 
			
		||||
 | 
			
		||||
    # Filtering
 | 
			
		||||
    'SEARCH_PARAM': 'search',
 | 
			
		||||
    'ORDERING_PARAM': 'ordering',
 | 
			
		||||
 | 
			
		||||
    # Authentication
 | 
			
		||||
    'UNAUTHENTICATED_USER': 'django.contrib.auth.models.AnonymousUser',
 | 
			
		||||
    'UNAUTHENTICATED_TOKEN': None,
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
| 
						 | 
				
			
			@ -7,9 +7,11 @@ from django.test import TestCase
 | 
			
		|||
from django.utils import unittest
 | 
			
		||||
from rest_framework import generics, serializers, status, filters
 | 
			
		||||
from rest_framework.compat import django_filters, patterns, url
 | 
			
		||||
from rest_framework.settings import api_settings
 | 
			
		||||
from rest_framework.test import APIRequestFactory
 | 
			
		||||
from rest_framework.tests.models import BasicModel
 | 
			
		||||
from .models import FilterableItem
 | 
			
		||||
from .utils import temporary_setting
 | 
			
		||||
 | 
			
		||||
factory = APIRequestFactory()
 | 
			
		||||
 | 
			
		||||
| 
						 | 
				
			
			@ -363,6 +365,24 @@ class SearchFilterTests(TestCase):
 | 
			
		|||
            ]
 | 
			
		||||
        )
 | 
			
		||||
 | 
			
		||||
    def test_search_with_nonstandard_search_param(self):
 | 
			
		||||
        with temporary_setting('SEARCH_PARAM', 'query', module=filters):
 | 
			
		||||
            class SearchListView(generics.ListAPIView):
 | 
			
		||||
                model = SearchFilterModel
 | 
			
		||||
                filter_backends = (filters.SearchFilter,)
 | 
			
		||||
                search_fields = ('title', 'text')
 | 
			
		||||
 | 
			
		||||
            view = SearchListView.as_view()
 | 
			
		||||
            request = factory.get('/', {'query': 'b'})
 | 
			
		||||
            response = view(request)
 | 
			
		||||
            self.assertEqual(
 | 
			
		||||
                response.data,
 | 
			
		||||
                [
 | 
			
		||||
                    {'id': 1, 'title': 'z', 'text': 'abc'},
 | 
			
		||||
                    {'id': 2, 'title': 'zz', 'text': 'bcd'}
 | 
			
		||||
                ]
 | 
			
		||||
            )
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
class OrdringFilterModel(models.Model):
 | 
			
		||||
    title = models.CharField(max_length=20)
 | 
			
		||||
| 
						 | 
				
			
			@ -520,6 +540,26 @@ class OrderingFilterTests(TestCase):
 | 
			
		|||
            ]
 | 
			
		||||
        )
 | 
			
		||||
 | 
			
		||||
    def test_ordering_with_nonstandard_ordering_param(self):
 | 
			
		||||
        with temporary_setting('ORDERING_PARAM', 'order', filters):
 | 
			
		||||
            class OrderingListView(generics.ListAPIView):
 | 
			
		||||
                model = OrdringFilterModel
 | 
			
		||||
                filter_backends = (filters.OrderingFilter,)
 | 
			
		||||
                ordering = ('title',)
 | 
			
		||||
                ordering_fields = ('text',)
 | 
			
		||||
 | 
			
		||||
            view = OrderingListView.as_view()
 | 
			
		||||
            request = factory.get('/', {'order': 'text'})
 | 
			
		||||
            response = view(request)
 | 
			
		||||
            self.assertEqual(
 | 
			
		||||
                response.data,
 | 
			
		||||
                [
 | 
			
		||||
                    {'id': 1, 'title': 'zyx', 'text': 'abc'},
 | 
			
		||||
                    {'id': 2, 'title': 'yxw', 'text': 'bcd'},
 | 
			
		||||
                    {'id': 3, 'title': 'xwv', 'text': 'cde'},
 | 
			
		||||
                ]
 | 
			
		||||
            )
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
class SensitiveOrderingFilterModel(models.Model):
 | 
			
		||||
    username = models.CharField(max_length=20)
 | 
			
		||||
| 
						 | 
				
			
			@ -618,4 +658,4 @@ class SensitiveOrderingFilterTests(TestCase):
 | 
			
		|||
                    {'id': 2, username_field: 'userB'}, # PassC
 | 
			
		||||
                    {'id': 3, username_field: 'userC'}, # PassA
 | 
			
		||||
                ]
 | 
			
		||||
            )
 | 
			
		||||
            )
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
							
								
								
									
										24
									
								
								rest_framework/tests/utils.py
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										24
									
								
								rest_framework/tests/utils.py
									
									
									
									
									
										Normal file
									
								
							| 
						 | 
				
			
			@ -0,0 +1,24 @@
 | 
			
		|||
from contextlib import contextmanager
 | 
			
		||||
from rest_framework.settings import api_settings
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
@contextmanager
 | 
			
		||||
def temporary_setting(setting, value, module=None):
 | 
			
		||||
    """
 | 
			
		||||
    Temporarily change value of setting for test.
 | 
			
		||||
 | 
			
		||||
    Optionally reload given module, useful when module uses value of setting on
 | 
			
		||||
    import.
 | 
			
		||||
    """
 | 
			
		||||
    original_value = getattr(api_settings, setting)
 | 
			
		||||
    setattr(api_settings, setting, value)
 | 
			
		||||
 | 
			
		||||
    if module is not None:
 | 
			
		||||
        reload(module)
 | 
			
		||||
 | 
			
		||||
    yield
 | 
			
		||||
 | 
			
		||||
    setattr(api_settings, setting, original_value)
 | 
			
		||||
 | 
			
		||||
    if module is not None:
 | 
			
		||||
        reload(module)
 | 
			
		||||
		Loading…
	
		Reference in New Issue
	
	Block a user