diff options
Diffstat (limited to 'tests/modeltests/field_subclassing/models.py')
| -rw-r--r-- | tests/modeltests/field_subclassing/models.py | 106 |
1 files changed, 106 insertions, 0 deletions
diff --git a/tests/modeltests/field_subclassing/models.py b/tests/modeltests/field_subclassing/models.py new file mode 100644 index 0000000000..6182266c22 --- /dev/null +++ b/tests/modeltests/field_subclassing/models.py @@ -0,0 +1,106 @@ +""" +Tests for field subclassing. +""" + +from django.db import models +from django.utils.encoding import force_unicode +from django.core import serializers + +class Small(object): + """ + A simple class to show that non-trivial Python objects can be used as + attributes. + """ + def __init__(self, first, second): + self.first, self.second = first, second + + def __unicode__(self): + return u'%s%s' % (force_unicode(self.first), force_unicode(self.second)) + + def __str__(self): + return unicode(self).encode('utf-8') + +class SmallField(models.Field): + """ + Turns the "Small" class into a Django field. Because of the similarities + with normal character fields and the fact that Small.__unicode__ does + something sensible, we don't need to implement a lot here. + """ + __metaclass__ = models.SubfieldBase + + def __init__(self, *args, **kwargs): + kwargs['max_length'] = 2 + super(SmallField, self).__init__(*args, **kwargs) + + def get_internal_type(self): + return 'CharField' + + def to_python(self, value): + if isinstance(value, Small): + return value + return Small(value[0], value[1]) + + def get_db_prep_save(self, value): + return unicode(value) + + def get_db_prep_lookup(self, lookup_type, value): + if lookup_type == 'exact': + return force_unicode(value) + if lookup_type == 'in': + return [force_unicode(v) for v in value] + if lookup_type == 'isnull': + return [] + raise TypeError('Invalid lookup type: %r' % lookup_type) + + def flatten_data(self, follow, obj=None): + return {self.attname: force_unicode(self._get_val_from_obj(obj))} + +class MyModel(models.Model): + name = models.CharField(max_length=10) + data = SmallField('small field') + + def __unicode__(self): + return force_unicode(self.name) + +__test__ = {'API_TESTS': ur""" +# Creating a model with custom fields is done as per normal. +>>> s = Small(1, 2) +>>> print s +12 +>>> m = MyModel(name='m', data=s) +>>> m.save() + +# Custom fields still have normal field's attributes. +>>> m._meta.get_field('data').verbose_name +'small field' + +# The m.data attribute has been initialised correctly. It's a Small object. +>>> m.data.first, m.data.second +(1, 2) + +# The data loads back from the database correctly and 'data' has the right type. +>>> m1 = MyModel.objects.get(pk=m.pk) +>>> isinstance(m1.data, Small) +True +>>> print m1.data +12 + +# We can do normal filtering on the custom field (and will get an error when we +# use a lookup type that does not make sense). +>>> s1 = Small(1, 3) +>>> s2 = Small('a', 'b') +>>> MyModel.objects.filter(data__in=[s, s1, s2]) +[<MyModel: m>] +>>> MyModel.objects.filter(data__lt=s) +Traceback (most recent call last): +... +TypeError: Invalid lookup type: 'lt' + +# Serialization works, too. +>>> stream = serializers.serialize("json", MyModel.objects.all()) +>>> stream +'[{"pk": 1, "model": "field_subclassing.mymodel", "fields": {"data": "12", "name": "m"}}]' +>>> obj = list(serializers.deserialize("json", stream))[0] +>>> obj.object == m +True +"""} |
