summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorTim Graham <timograham@gmail.com>2018-04-03 11:12:56 -0400
committerGitHub <noreply@github.com>2018-04-03 11:12:56 -0400
commit4f7467b6905482a5d826c2815dcf8c6dd332340d (patch)
tree991f63928f19ffa22c183a6f5b08a61b05bebb7c
parent167d98528a2f38e370507ffe4f352b3406f5c5e1 (diff)
Refs #28577 -- Added check for HStoreField to prevent mutable default.
-rw-r--r--django/contrib/postgres/fields/hstore.py5
-rw-r--r--tests/postgres_tests/test_hstore.py34
2 files changed, 35 insertions, 4 deletions
diff --git a/django/contrib/postgres/fields/hstore.py b/django/contrib/postgres/fields/hstore.py
index d47b34d459..39f074b763 100644
--- a/django/contrib/postgres/fields/hstore.py
+++ b/django/contrib/postgres/fields/hstore.py
@@ -6,15 +6,18 @@ from django.core import exceptions
from django.db.models import Field, TextField, Transform
from django.utils.translation import gettext_lazy as _
+from .mixins import CheckFieldDefaultMixin
+
__all__ = ['HStoreField']
-class HStoreField(Field):
+class HStoreField(CheckFieldDefaultMixin, Field):
empty_strings_allowed = False
description = _('Map of strings to strings/nulls')
default_error_messages = {
'not_a_string': _('The value of "%(key)s" is not a string or null.'),
}
+ _default_hint = ('dict', '{}')
def db_type(self, connection):
return 'hstore'
diff --git a/tests/postgres_tests/test_hstore.py b/tests/postgres_tests/test_hstore.py
index b58e5e5e20..a51cb4e66f 100644
--- a/tests/postgres_tests/test_hstore.py
+++ b/tests/postgres_tests/test_hstore.py
@@ -1,11 +1,11 @@
import json
-from django.core import exceptions, serializers
+from django.core import checks, exceptions, serializers
from django.forms import Form
-from django.test.utils import modify_settings
+from django.test.utils import isolate_apps, modify_settings
from . import PostgreSQLTestCase
-from .models import HStoreModel
+from .models import HStoreModel, PostgreSQLModel
try:
from django.contrib.postgres import forms
@@ -190,6 +190,34 @@ class TestQuerying(HStoreTestCase):
)
+@isolate_apps('postgres_tests')
+class TestChecks(PostgreSQLTestCase):
+
+ def test_invalid_default(self):
+ class MyModel(PostgreSQLModel):
+ field = HStoreField(default={})
+
+ model = MyModel()
+ self.assertEqual(model.check(), [
+ checks.Warning(
+ msg=(
+ "HStoreField default should be a callable instead of an "
+ "instance so that it's not shared between all field "
+ "instances."
+ ),
+ hint='Use a callable instead, e.g., use `dict` instead of `{}`.',
+ obj=MyModel._meta.get_field('field'),
+ id='postgres.E003',
+ )
+ ])
+
+ def test_valid_default(self):
+ class MyModel(PostgreSQLModel):
+ field = HStoreField(default=dict)
+
+ self.assertEqual(MyModel().check(), [])
+
+
class TestSerialization(HStoreTestCase):
test_data = json.dumps([{
'model': 'postgres_tests.hstoremodel',