Fixed #26120 -- Made HStoreField cast keys and values to strings.
HStoreField now converts all keys and values to string before they're saved to the database.
This commit is contained in:
parent
93897a6a75
commit
8dea9f089d
|
@ -5,6 +5,7 @@ from django.contrib.postgres.fields.array import ArrayField
|
||||||
from django.core import exceptions
|
from django.core import exceptions
|
||||||
from django.db.models import Field, TextField, Transform
|
from django.db.models import Field, TextField, Transform
|
||||||
from django.utils import six
|
from django.utils import six
|
||||||
|
from django.utils.encoding import force_text
|
||||||
from django.utils.translation import ugettext_lazy as _
|
from django.utils.translation import ugettext_lazy as _
|
||||||
|
|
||||||
__all__ = ['HStoreField']
|
__all__ = ['HStoreField']
|
||||||
|
@ -51,6 +52,22 @@ class HStoreField(Field):
|
||||||
defaults.update(kwargs)
|
defaults.update(kwargs)
|
||||||
return super(HStoreField, self).formfield(**defaults)
|
return super(HStoreField, self).formfield(**defaults)
|
||||||
|
|
||||||
|
def get_prep_value(self, value):
|
||||||
|
value = super(HStoreField, self).get_prep_value(value)
|
||||||
|
|
||||||
|
if isinstance(value, dict):
|
||||||
|
prep_value = {}
|
||||||
|
for key, val in value.items():
|
||||||
|
key = force_text(key)
|
||||||
|
if val is not None:
|
||||||
|
val = force_text(val)
|
||||||
|
prep_value[key] = val
|
||||||
|
value = prep_value
|
||||||
|
|
||||||
|
if isinstance(value, list):
|
||||||
|
value = [force_text(item) for item in value]
|
||||||
|
|
||||||
|
return value
|
||||||
|
|
||||||
HStoreField.register_lookup(lookups.DataContains)
|
HStoreField.register_lookup(lookups.DataContains)
|
||||||
HStoreField.register_lookup(lookups.ContainedBy)
|
HStoreField.register_lookup(lookups.ContainedBy)
|
||||||
|
|
|
@ -129,7 +129,8 @@ Minor features
|
||||||
:mod:`django.contrib.postgres`
|
:mod:`django.contrib.postgres`
|
||||||
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
|
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
|
||||||
|
|
||||||
* ...
|
* For convenience, :class:`~django.contrib.postgres.fields.HStoreField` now
|
||||||
|
casts its keys and values to strings.
|
||||||
|
|
||||||
:mod:`django.contrib.redirects`
|
:mod:`django.contrib.redirects`
|
||||||
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
|
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
|
||||||
|
|
|
@ -1,3 +1,6 @@
|
||||||
|
# -*- coding: utf-8 -*-
|
||||||
|
from __future__ import unicode_literals
|
||||||
|
|
||||||
import json
|
import json
|
||||||
|
|
||||||
from django.core import exceptions, serializers
|
from django.core import exceptions, serializers
|
||||||
|
@ -37,6 +40,20 @@ class SimpleTests(PostgreSQLTestCase):
|
||||||
reloaded = HStoreModel.objects.get()
|
reloaded = HStoreModel.objects.get()
|
||||||
self.assertEqual(reloaded.field, value)
|
self.assertEqual(reloaded.field, value)
|
||||||
|
|
||||||
|
def test_key_val_cast_to_string(self):
|
||||||
|
value = {'a': 1, 'b': 'B', 2: 'c', 'ï': 'ê', b'x': b'test'}
|
||||||
|
expected_value = {'a': '1', 'b': 'B', '2': 'c', 'ï': 'ê', 'x': 'test'}
|
||||||
|
|
||||||
|
instance = HStoreModel.objects.create(field=value)
|
||||||
|
instance = HStoreModel.objects.get()
|
||||||
|
self.assertDictEqual(instance.field, expected_value)
|
||||||
|
|
||||||
|
instance = HStoreModel.objects.get(field__a=1)
|
||||||
|
self.assertDictEqual(instance.field, expected_value)
|
||||||
|
|
||||||
|
instance = HStoreModel.objects.get(field__has_keys=[2, 'a', 'ï'])
|
||||||
|
self.assertDictEqual(instance.field, expected_value)
|
||||||
|
|
||||||
|
|
||||||
class TestQuerying(PostgreSQLTestCase):
|
class TestQuerying(PostgreSQLTestCase):
|
||||||
|
|
||||||
|
|
Loading…
Reference in New Issue