Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Test for #123 #124

Open
wants to merge 1 commit into
base: master
Choose a base branch
from
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
50 changes: 49 additions & 1 deletion tests/django_hstore_tests/models.py
Original file line number Diff line number Diff line change
Expand Up @@ -92,6 +92,46 @@ class Meta:
unique_together = ('name', 'data')

if get_version()[0:3] >= '1.6':
class CustomType(object):
"""Custom type, for use as an example for (de)serialization."""
def __init__(self, value):
self.value = value

def __eq__(self, other):
return isinstance(other, CustomType) and \
self.value == other.value

@classmethod
def deserialize(cls, raw):
if raw:
assert raw.startswith('[')
assert raw.endswith(']')
return cls(raw[1:-1])

def serialize(self):
return '[' + self.value + ']'


class CustomField(models.Field):
def db_type(self, connection):
return 'text'

def from_db_value(self, value, expression, connection, context):
"""DB value -> Python type"""
return CustomType.deserialize(value)

def get_prep_value(self, value):
"""Python type -> DB value"""
return value.serialize()

def to_python(self, value):
"""text or Python type -> Python type"""
if isinstance(value, CustomType):
return value

return CustomType.deserialize(value)


class SchemaDataBag(HStoreModel):
name = models.CharField(max_length=32)
data = hstore.DictionaryField(schema=[
Expand Down Expand Up @@ -200,6 +240,14 @@ class SchemaDataBag(HStoreModel):
'blank': True
}
},
{
'name': 'custom',
'class': CustomField,
'kwargs': {
'blank': True,
'null': True
}
},
])

class NullSchemaDataBag(HStoreModel):
Expand All @@ -223,7 +271,7 @@ class NullSchemaDataBag(HStoreModel):

__all__.append('SchemaDataBag')
__all__.append('NullSchemaDataBag')


# if geodjango is in use define Location model, which contains GIS data
if GEODJANGO_INSTALLED:
Expand Down
14 changes: 13 additions & 1 deletion tests/django_hstore_tests/tests/test_schema_mode.py
Original file line number Diff line number Diff line change
Expand Up @@ -19,7 +19,8 @@
from django_hstore import hstore
from django_hstore.virtual import create_hstore_virtual_field

from django_hstore_tests.models import SchemaDataBag, NullSchemaDataBag
from django_hstore_tests.models import (CustomType, SchemaDataBag,
NullSchemaDataBag)


MIGRATION_PATH = '{0}/../{1}'.format(os.path.dirname(__file__), 'migrations')
Expand Down Expand Up @@ -65,6 +66,17 @@ def test_dict_get(self):
self.assertEqual(d.get('default_test', 'default'), 'default')
self.assertIsNone(d.get('default_test'))

def test_save_and_reload_custom_type(self):
d = SchemaDataBag()
v = CustomType('some value')
d.custom = v
self.assertEqual(d.custom, v)

def test_serializing_custom_type(self):
d = SchemaDataBag()
d.custom = CustomType('some value')
self.assertEqual(dict.get(d.data, 'custom'), '[some value]')
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I got the previous test to pass but here I have some doubts.

Isn't dict.get(d.data, 'custom') the same as d.data.get('custom')?
If that is correct it should return the CustomType instance, not the serialized value "[some value]".
If I'm not wrong the serialized value must be used only before storing the value into the database, which would mean this is not the right way to test for the desired behaviour.
What do you think?

PS: in django-hstore's VirtualField implementation, calling d.data.get('custom') is equivalent to calling d.custom

Copy link
Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

If the first test passes even after saving/reloading the instance, then this one is not really needed. dict.get(d.data, 'custom') is pretty much what d.data.get('custom') calls when calling super().get().

When writing this test I assumed the serialization would be done when assigning values, and only later did I realize that's not how native Django fields work.

Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Ok.


def test_virtual_field_default_value(self):
d = SchemaDataBag()
self.assertEqual(d.number, 0)
Expand Down