Add tests for HTML_CUTOFF setting and fix issue where setting it to None would raise an exception.

This commit is contained in:
Tadhg O'Higgins 2017-05-24 16:46:18 -07:00
parent 871ce34983
commit 99782c2160
3 changed files with 74 additions and 10 deletions

View File

@ -75,7 +75,8 @@ class PKOnlyObject(object):
# rather than the parent serializer. # rather than the parent serializer.
MANY_RELATION_KWARGS = ( MANY_RELATION_KWARGS = (
'read_only', 'write_only', 'required', 'default', 'initial', 'source', 'read_only', 'write_only', 'required', 'default', 'initial', 'source',
'label', 'help_text', 'style', 'error_messages', 'allow_empty' 'label', 'help_text', 'style', 'error_messages', 'allow_empty',
'html_cutoff', 'html_cutoff_text'
) )
@ -86,10 +87,12 @@ class RelatedField(Field):
def __init__(self, **kwargs): def __init__(self, **kwargs):
self.queryset = kwargs.pop('queryset', self.queryset) self.queryset = kwargs.pop('queryset', self.queryset)
self.html_cutoff = kwargs.pop(
'html_cutoff', cutoff_from_settings = api_settings.HTML_SELECT_CUTOFF
self.html_cutoff or int(api_settings.HTML_SELECT_CUTOFF) if cutoff_from_settings is not None:
) cutoff_from_settings = int(cutoff_from_settings)
self.html_cutoff = kwargs.pop('html_cutoff', cutoff_from_settings)
self.html_cutoff_text = kwargs.pop( self.html_cutoff_text = kwargs.pop(
'html_cutoff_text', 'html_cutoff_text',
self.html_cutoff_text or _(api_settings.HTML_SELECT_CUTOFF_TEXT) self.html_cutoff_text or _(api_settings.HTML_SELECT_CUTOFF_TEXT)
@ -466,10 +469,12 @@ class ManyRelatedField(Field):
def __init__(self, child_relation=None, *args, **kwargs): def __init__(self, child_relation=None, *args, **kwargs):
self.child_relation = child_relation self.child_relation = child_relation
self.allow_empty = kwargs.pop('allow_empty', True) self.allow_empty = kwargs.pop('allow_empty', True)
self.html_cutoff = kwargs.pop(
'html_cutoff', cutoff_from_settings = api_settings.HTML_SELECT_CUTOFF
self.html_cutoff or int(api_settings.HTML_SELECT_CUTOFF) if cutoff_from_settings is not None:
) cutoff_from_settings = int(cutoff_from_settings)
self.html_cutoff = kwargs.pop('html_cutoff', cutoff_from_settings)
self.html_cutoff_text = kwargs.pop( self.html_cutoff_text = kwargs.pop(
'html_cutoff_text', 'html_cutoff_text',
self.html_cutoff_text or _(api_settings.HTML_SELECT_CUTOFF_TEXT) self.html_cutoff_text or _(api_settings.HTML_SELECT_CUTOFF_TEXT)

View File

@ -1,12 +1,13 @@
import uuid import uuid
import pytest import pytest
from _pytest.monkeypatch import MonkeyPatch
from django.conf.urls import url from django.conf.urls import url
from django.core.exceptions import ImproperlyConfigured from django.core.exceptions import ImproperlyConfigured
from django.test import override_settings from django.test import override_settings
from django.utils.datastructures import MultiValueDict from django.utils.datastructures import MultiValueDict
from rest_framework import serializers from rest_framework import relations, serializers
from rest_framework.fields import empty from rest_framework.fields import empty
from rest_framework.test import APISimpleTestCase from rest_framework.test import APISimpleTestCase
@ -25,6 +26,61 @@ class TestStringRelatedField(APISimpleTestCase):
assert representation == '<MockObject name=foo, pk=1>' assert representation == '<MockObject name=foo, pk=1>'
class MockApiSettings(object):
def __init__(self, cutoff, cutoff_text):
self.HTML_SELECT_CUTOFF = cutoff
self.HTML_SELECT_CUTOFF_TEXT = cutoff_text
class TestRelatedFieldHTMLCutoff(APISimpleTestCase):
def setUp(self):
self.queryset = MockQueryset([
MockObject(pk=i, name=str(i)) for i in range(0, 1100)
])
self.monkeypatch = MonkeyPatch()
def test_no_settings(self):
# The default is 1,000, so sans settings it should be 1,000 plus one.
for many in (False, True):
field = serializers.PrimaryKeyRelatedField(queryset=self.queryset,
many=many)
options = list(field.iter_options())
assert len(options) == 1001
assert options[-1].display_text == "More than 1000 items..."
def test_settings_cutoff(self):
self.monkeypatch.setattr(relations, "api_settings",
MockApiSettings(2, "Cut Off"))
for many in (False, True):
field = serializers.PrimaryKeyRelatedField(queryset=self.queryset,
many=many)
options = list(field.iter_options())
assert len(options) == 3 # 2 real items plus the 'Cut Off' item.
assert options[-1].display_text == "Cut Off"
def test_settings_cutoff_none(self):
# Setting it to None should mean no limit; the default limit is 1,000.
self.monkeypatch.setattr(relations, "api_settings",
MockApiSettings(None, "Cut Off"))
for many in (False, True):
field = serializers.PrimaryKeyRelatedField(queryset=self.queryset,
many=many)
options = list(field.iter_options())
assert len(options) == 1100
def test_settings_kwargs_cutoff(self):
# The explicit argument should override the settings.
self.monkeypatch.setattr(relations, "api_settings",
MockApiSettings(2, "Cut Off"))
for many in (False, True):
field = serializers.PrimaryKeyRelatedField(queryset=self.queryset,
many=many,
html_cutoff=100)
options = list(field.iter_options())
assert len(options) == 101
assert options[-1].display_text == "Cut Off"
class TestPrimaryKeyRelatedField(APISimpleTestCase): class TestPrimaryKeyRelatedField(APISimpleTestCase):
def setUp(self): def setUp(self):
self.queryset = MockQueryset([ self.queryset = MockQueryset([

View File

@ -20,6 +20,9 @@ class MockQueryset(object):
def __init__(self, iterable): def __init__(self, iterable):
self.items = iterable self.items = iterable
def __getitem__(self, val):
return self.items[val]
def get(self, **lookup): def get(self, **lookup):
for item in self.items: for item in self.items:
if all([ if all([