From 222c73261650201f5ce99e8dd4b1ce0d30a69eb4 Mon Sep 17 00:00:00 2001 From: Alex Gaynor Date: Tue, 2 Nov 2010 18:40:53 +0000 Subject: [PATCH] Fixed #10728 -- corrected subclassing of Fields who use the SubfieldBase metaclass. Thanks to G2P and George Sakkis for their work on the patch. git-svn-id: http://code.djangoproject.com/svn/django/trunk@14443 bcc190cf-cafb-0310-a4f2-bffc1f526a37 --- django/db/models/fields/subclassing.py | 7 ++++--- tests/modeltests/field_subclassing/fields.py | 3 +++ tests/modeltests/field_subclassing/models.py | 5 ++++- tests/modeltests/field_subclassing/tests.py | 8 +++++++- 4 files changed, 18 insertions(+), 5 deletions(-) diff --git a/django/db/models/fields/subclassing.py b/django/db/models/fields/subclassing.py index 148a998f1c..759373e4d0 100644 --- a/django/db/models/fields/subclassing.py +++ b/django/db/models/fields/subclassing.py @@ -79,7 +79,8 @@ class SubfieldBase(LegacyConnection): def __new__(cls, base, name, attrs): new_class = super(SubfieldBase, cls).__new__(cls, base, name, attrs) new_class.contribute_to_class = make_contrib( - attrs.get('contribute_to_class')) + new_class, attrs.get('contribute_to_class') + ) return new_class class Creator(object): @@ -97,7 +98,7 @@ class Creator(object): def __set__(self, obj, value): obj.__dict__[self.field.name] = self.field.to_python(value) -def make_contrib(func=None): +def make_contrib(superclass, func=None): """ Returns a suitable contribute_to_class() method for the Field subclass. @@ -110,7 +111,7 @@ def make_contrib(func=None): if func: func(self, cls, name) else: - super(self.__class__, self).contribute_to_class(cls, name) + super(superclass, self).contribute_to_class(cls, name) setattr(cls, self.name, Creator(self)) return contribute_to_class diff --git a/tests/modeltests/field_subclassing/fields.py b/tests/modeltests/field_subclassing/fields.py index f667310c58..ba1eb90823 100644 --- a/tests/modeltests/field_subclassing/fields.py +++ b/tests/modeltests/field_subclassing/fields.py @@ -52,6 +52,9 @@ class SmallField(models.Field): return [] raise TypeError('Invalid lookup type: %r' % lookup_type) +class SmallerField(SmallField): + pass + class JSONField(models.TextField): __metaclass__ = models.SubfieldBase diff --git a/tests/modeltests/field_subclassing/models.py b/tests/modeltests/field_subclassing/models.py index 4a55b72961..b0d83365c5 100644 --- a/tests/modeltests/field_subclassing/models.py +++ b/tests/modeltests/field_subclassing/models.py @@ -5,7 +5,7 @@ Tests for field subclassing. from django.db import models from django.utils.encoding import force_unicode -from fields import Small, SmallField, JSONField +from fields import Small, SmallField, SmallerField, JSONField class MyModel(models.Model): @@ -15,5 +15,8 @@ class MyModel(models.Model): def __unicode__(self): return force_unicode(self.name) +class OtherModel(models.Model): + data = SmallerField() + class DataModel(models.Model): data = JSONField() diff --git a/tests/modeltests/field_subclassing/tests.py b/tests/modeltests/field_subclassing/tests.py index ba7148a654..25f51600b9 100644 --- a/tests/modeltests/field_subclassing/tests.py +++ b/tests/modeltests/field_subclassing/tests.py @@ -2,7 +2,7 @@ from django.core import serializers from django.test import TestCase from fields import Small -from models import DataModel, MyModel +from models import DataModel, MyModel, OtherModel class CustomField(TestCase): @@ -73,3 +73,9 @@ class CustomField(TestCase): ], lambda m: str(m.data) ) + + def test_field_subclassing(self): + o = OtherModel.objects.create(data=Small("a", "b")) + o = OtherModel.objects.get() + self.assertEqual(o.data.first, "a") + self.assertEqual(o.data.second, "b")