소스 검색

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.
Greg Chapple 9 년 전
부모
커밋
8dea9f089d
3개의 변경된 파일36개의 추가작업 그리고 1개의 파일을 삭제
  1. 17 0
      django/contrib/postgres/fields/hstore.py
  2. 2 1
      docs/releases/1.10.txt
  3. 17 0
      tests/postgres_tests/test_hstore.py

+ 17 - 0
django/contrib/postgres/fields/hstore.py

@@ -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
docs/releases/1.10.txt

@@ -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
tests/postgres_tests/test_hstore.py

@@ -1,3 +1,6 @@
+# -*- 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):