Add a max_length param to the ListField (#2107)
This is similar to the `max_length` param of a `StringField`. Sometimes you don't want your lists to be able to grow indefinitely.
This commit is contained in:
parent
b47669403b
commit
82f0eb1cbc
@ -916,8 +916,9 @@ class ListField(ComplexBaseField):
|
|||||||
Required means it cannot be empty - as the default for ListFields is []
|
Required means it cannot be empty - as the default for ListFields is []
|
||||||
"""
|
"""
|
||||||
|
|
||||||
def __init__(self, field=None, **kwargs):
|
def __init__(self, field=None, max_length=None, **kwargs):
|
||||||
self.field = field
|
self.field = field
|
||||||
|
self.max_length = max_length
|
||||||
kwargs.setdefault("default", lambda: [])
|
kwargs.setdefault("default", lambda: [])
|
||||||
super(ListField, self).__init__(**kwargs)
|
super(ListField, self).__init__(**kwargs)
|
||||||
|
|
||||||
@ -939,9 +940,21 @@ class ListField(ComplexBaseField):
|
|||||||
"""Make sure that a list of valid fields is being used."""
|
"""Make sure that a list of valid fields is being used."""
|
||||||
if not isinstance(value, (list, tuple, BaseQuerySet)):
|
if not isinstance(value, (list, tuple, BaseQuerySet)):
|
||||||
self.error("Only lists and tuples may be used in a list field")
|
self.error("Only lists and tuples may be used in a list field")
|
||||||
|
|
||||||
|
# Validate that max_length is not exceeded.
|
||||||
|
# NOTE It's still possible to bypass this enforcement by using $push.
|
||||||
|
# However, if the document is reloaded after $push and then re-saved,
|
||||||
|
# the validation error will be raised.
|
||||||
|
if self.max_length is not None and len(value) > self.max_length:
|
||||||
|
self.error("List is too long")
|
||||||
|
|
||||||
super(ListField, self).validate(value)
|
super(ListField, self).validate(value)
|
||||||
|
|
||||||
def prepare_query_value(self, op, value):
|
def prepare_query_value(self, op, value):
|
||||||
|
# Validate that the `set` operator doesn't contain more items than `max_length`.
|
||||||
|
if op == "set" and self.max_length is not None and len(value) > self.max_length:
|
||||||
|
self.error("List is too long")
|
||||||
|
|
||||||
if self.field:
|
if self.field:
|
||||||
|
|
||||||
# If the value is iterable and it's not a string nor a
|
# If the value is iterable and it's not a string nor a
|
||||||
|
@ -1010,6 +1010,38 @@ class FieldTest(MongoDBTestCase):
|
|||||||
e.mapping = ["abc"]
|
e.mapping = ["abc"]
|
||||||
e.save()
|
e.save()
|
||||||
|
|
||||||
|
def test_list_field_max_length(self):
|
||||||
|
"""Ensure ListField's max_length is respected."""
|
||||||
|
|
||||||
|
class Foo(Document):
|
||||||
|
items = ListField(IntField(), max_length=5)
|
||||||
|
|
||||||
|
foo = Foo()
|
||||||
|
for i in range(1, 7):
|
||||||
|
foo.items.append(i)
|
||||||
|
if i < 6:
|
||||||
|
foo.save()
|
||||||
|
else:
|
||||||
|
with self.assertRaises(ValidationError) as cm:
|
||||||
|
foo.save()
|
||||||
|
self.assertIn("List is too long", str(cm.exception))
|
||||||
|
|
||||||
|
def test_list_field_max_length(self):
|
||||||
|
"""Ensure ListField's max_length is respected."""
|
||||||
|
|
||||||
|
class Foo(Document):
|
||||||
|
items = ListField(IntField(), max_length=5)
|
||||||
|
|
||||||
|
foo = Foo()
|
||||||
|
for i in range(1, 7):
|
||||||
|
foo.items.append(i)
|
||||||
|
if i < 6:
|
||||||
|
foo.save()
|
||||||
|
else:
|
||||||
|
with self.assertRaises(ValidationError) as cm:
|
||||||
|
foo.save()
|
||||||
|
self.assertIn("List is too long", str(cm.exception))
|
||||||
|
|
||||||
def test_list_field_rejects_strings(self):
|
def test_list_field_rejects_strings(self):
|
||||||
"""Strings aren't valid list field data types."""
|
"""Strings aren't valid list field data types."""
|
||||||
|
|
||||||
|
Loading…
x
Reference in New Issue
Block a user