Commit 8dea9f08 authored by Greg Chapple's avatar Greg Chapple Committed by Tim Graham
Browse files

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.
parent 93897a6a
Loading
Loading
Loading
Loading
+17 −0
Original line number Diff line number Diff line
@@ -5,6 +5,7 @@ from django.contrib.postgres.fields.array import ArrayField
from django.core import exceptions
from django.db.models import Field, TextField, Transform
from django.utils import six
from django.utils.encoding import force_text
from django.utils.translation import ugettext_lazy as _

__all__ = ['HStoreField']
@@ -51,6 +52,22 @@ class HStoreField(Field):
        defaults.update(kwargs)
        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.ContainedBy)
+2 −1
Original line number Diff line number Diff line
@@ -129,7 +129,8 @@ Minor features
:mod:`django.contrib.postgres`
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~

* ...
* For convenience, :class:`~django.contrib.postgres.fields.HStoreField` now
  casts its keys and values to strings.

:mod:`django.contrib.redirects`
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
+17 −0
Original line number Diff line number Diff line
# -*- coding: utf-8 -*-
from __future__ import unicode_literals

import json

from django.core import exceptions, serializers
@@ -37,6 +40,20 @@ class SimpleTests(PostgreSQLTestCase):
        reloaded = HStoreModel.objects.get()
        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):