Skip to content

Commit e2157fb

Browse files
authored
Merge pull request #5174 from tadhg-ohiggins/html_cutoff_none
Fix exception when HTML_CUTOFF is set to None
2 parents 6c7a7cc + 99782c2 commit e2157fb

File tree

3 files changed

+74
-10
lines changed

3 files changed

+74
-10
lines changed

rest_framework/relations.py

Lines changed: 14 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -75,7 +75,8 @@ def __str__(self):
7575
# rather than the parent serializer.
7676
MANY_RELATION_KWARGS = (
7777
'read_only', 'write_only', 'required', 'default', 'initial', 'source',
78-
'label', 'help_text', 'style', 'error_messages', 'allow_empty'
78+
'label', 'help_text', 'style', 'error_messages', 'allow_empty',
79+
'html_cutoff', 'html_cutoff_text'
7980
)
8081

8182

@@ -86,10 +87,12 @@ class RelatedField(Field):
8687

8788
def __init__(self, **kwargs):
8889
self.queryset = kwargs.pop('queryset', self.queryset)
89-
self.html_cutoff = kwargs.pop(
90-
'html_cutoff',
91-
self.html_cutoff or int(api_settings.HTML_SELECT_CUTOFF)
92-
)
90+
91+
cutoff_from_settings = api_settings.HTML_SELECT_CUTOFF
92+
if cutoff_from_settings is not None:
93+
cutoff_from_settings = int(cutoff_from_settings)
94+
self.html_cutoff = kwargs.pop('html_cutoff', cutoff_from_settings)
95+
9396
self.html_cutoff_text = kwargs.pop(
9497
'html_cutoff_text',
9598
self.html_cutoff_text or _(api_settings.HTML_SELECT_CUTOFF_TEXT)
@@ -466,10 +469,12 @@ class ManyRelatedField(Field):
466469
def __init__(self, child_relation=None, *args, **kwargs):
467470
self.child_relation = child_relation
468471
self.allow_empty = kwargs.pop('allow_empty', True)
469-
self.html_cutoff = kwargs.pop(
470-
'html_cutoff',
471-
self.html_cutoff or int(api_settings.HTML_SELECT_CUTOFF)
472-
)
472+
473+
cutoff_from_settings = api_settings.HTML_SELECT_CUTOFF
474+
if cutoff_from_settings is not None:
475+
cutoff_from_settings = int(cutoff_from_settings)
476+
self.html_cutoff = kwargs.pop('html_cutoff', cutoff_from_settings)
477+
473478
self.html_cutoff_text = kwargs.pop(
474479
'html_cutoff_text',
475480
self.html_cutoff_text or _(api_settings.HTML_SELECT_CUTOFF_TEXT)

tests/test_relations.py

Lines changed: 57 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,12 +1,13 @@
11
import uuid
22

33
import pytest
4+
from _pytest.monkeypatch import MonkeyPatch
45
from django.conf.urls import url
56
from django.core.exceptions import ImproperlyConfigured
67
from django.test import override_settings
78
from django.utils.datastructures import MultiValueDict
89

9-
from rest_framework import serializers
10+
from rest_framework import relations, serializers
1011
from rest_framework.fields import empty
1112
from rest_framework.test import APISimpleTestCase
1213

@@ -25,6 +26,61 @@ def test_string_related_representation(self):
2526
assert representation == '<MockObject name=foo, pk=1>'
2627

2728

29+
class MockApiSettings(object):
30+
def __init__(self, cutoff, cutoff_text):
31+
self.HTML_SELECT_CUTOFF = cutoff
32+
self.HTML_SELECT_CUTOFF_TEXT = cutoff_text
33+
34+
35+
class TestRelatedFieldHTMLCutoff(APISimpleTestCase):
36+
def setUp(self):
37+
self.queryset = MockQueryset([
38+
MockObject(pk=i, name=str(i)) for i in range(0, 1100)
39+
])
40+
self.monkeypatch = MonkeyPatch()
41+
42+
def test_no_settings(self):
43+
# The default is 1,000, so sans settings it should be 1,000 plus one.
44+
for many in (False, True):
45+
field = serializers.PrimaryKeyRelatedField(queryset=self.queryset,
46+
many=many)
47+
options = list(field.iter_options())
48+
assert len(options) == 1001
49+
assert options[-1].display_text == "More than 1000 items..."
50+
51+
def test_settings_cutoff(self):
52+
self.monkeypatch.setattr(relations, "api_settings",
53+
MockApiSettings(2, "Cut Off"))
54+
for many in (False, True):
55+
field = serializers.PrimaryKeyRelatedField(queryset=self.queryset,
56+
many=many)
57+
options = list(field.iter_options())
58+
assert len(options) == 3 # 2 real items plus the 'Cut Off' item.
59+
assert options[-1].display_text == "Cut Off"
60+
61+
def test_settings_cutoff_none(self):
62+
# Setting it to None should mean no limit; the default limit is 1,000.
63+
self.monkeypatch.setattr(relations, "api_settings",
64+
MockApiSettings(None, "Cut Off"))
65+
for many in (False, True):
66+
field = serializers.PrimaryKeyRelatedField(queryset=self.queryset,
67+
many=many)
68+
options = list(field.iter_options())
69+
assert len(options) == 1100
70+
71+
def test_settings_kwargs_cutoff(self):
72+
# The explicit argument should override the settings.
73+
self.monkeypatch.setattr(relations, "api_settings",
74+
MockApiSettings(2, "Cut Off"))
75+
for many in (False, True):
76+
field = serializers.PrimaryKeyRelatedField(queryset=self.queryset,
77+
many=many,
78+
html_cutoff=100)
79+
options = list(field.iter_options())
80+
assert len(options) == 101
81+
assert options[-1].display_text == "Cut Off"
82+
83+
2884
class TestPrimaryKeyRelatedField(APISimpleTestCase):
2985
def setUp(self):
3086
self.queryset = MockQueryset([

tests/utils.py

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -20,6 +20,9 @@ class MockQueryset(object):
2020
def __init__(self, iterable):
2121
self.items = iterable
2222

23+
def __getitem__(self, val):
24+
return self.items[val]
25+
2326
def get(self, **lookup):
2427
for item in self.items:
2528
if all([

0 commit comments

Comments
 (0)
pFad - Phonifier reborn

Pfad - The Proxy pFad of © 2024 Garber Painting. All rights reserved.

Note: This service is not intended for secure transactions such as banking, social media, email, or purchasing. Use at your own risk. We assume no liability whatsoever for broken pages.


Alternative Proxies:

Alternative Proxy

pFad Proxy

pFad v3 Proxy

pFad v4 Proxy