1
0
mirror of https://github.com/django/django.git synced 2025-10-24 14:16:09 +00:00

Fixed #28577 -- Added checks for ArrayField and JSONField to prevent mutable defaults.

This commit is contained in:
Flávio Juvenal
2017-08-17 16:21:35 -07:00
committed by Tim Graham
parent 5ceaf14686
commit f6e1789654
8 changed files with 112 additions and 6 deletions

View File

@@ -10,17 +10,19 @@ from django.utils.inspect import func_supports_parameter
from django.utils.translation import gettext_lazy as _
from ..utils import prefix_validation_error
from .mixins import CheckFieldDefaultMixin
from .utils import AttributeSetter
__all__ = ['ArrayField']
class ArrayField(Field):
class ArrayField(CheckFieldDefaultMixin, Field):
empty_strings_allowed = False
default_error_messages = {
'item_invalid': _('Item %(nth)s in the array did not validate: '),
'nested_array_mismatch': _('Nested arrays must have the same length.'),
}
_default_hint = ('list', '[]')
def __init__(self, base_field, size=None, **kwargs):
self.base_field = base_field

View File

@@ -9,6 +9,8 @@ from django.db.models import (
)
from django.utils.translation import gettext_lazy as _
from .mixins import CheckFieldDefaultMixin
__all__ = ['JSONField']
@@ -25,12 +27,13 @@ class JsonAdapter(Json):
return json.dumps(obj, **options)
class JSONField(Field):
class JSONField(CheckFieldDefaultMixin, Field):
empty_strings_allowed = False
description = _('A JSON object')
default_error_messages = {
'invalid': _("Value must be valid JSON."),
}
_default_hint = ('dict', '{}')
def __init__(self, verbose_name=None, name=None, encoder=None, **kwargs):
if encoder and not callable(encoder):

View File

@@ -0,0 +1,29 @@
from django.core import checks
class CheckFieldDefaultMixin:
_default_hint = ('<valid default>', '<invalid default>')
def _check_default(self):
if self.has_default() and self.default is not None and not callable(self.default):
return [
checks.Warning(
"%s default should be a callable instead of an instance so "
"that it's not shared between all field instances." % (
self.__class__.__name__,
),
hint=(
'Use a callable instead, e.g., use `%s` instead of '
'`%s`.' % self._default_hint
),
obj=self,
id='postgres.E003',
)
]
else:
return []
def check(self, **kwargs):
errors = super().check(**kwargs)
errors.extend(self._check_default())
return errors