Browse Source

Don't use SubfieldBase as it's not compatible with Django 1.10

Use fix used on Wagtail https://github.com/torchbox/wagtail/pull/2736 to avoid
using SubfieldBase for custom fields
master
Pete Graham 9 years ago
parent
commit
082f466cd6
1 changed files with 42 additions and 4 deletions
  1. 42
    4
      src/oscar/models/fields/__init__.py

+ 42
- 4
src/oscar/models/fields/__init__.py View File

@@ -1,6 +1,5 @@
1 1
 from django.core.exceptions import ImproperlyConfigured
2 2
 from django.db.models.fields import CharField, DecimalField
3
-from django.db.models import SubfieldBase
4 3
 from django.utils import six
5 4
 from django.utils.translation import ugettext_lazy as _
6 5
 
@@ -13,6 +12,23 @@ from .autoslugfield import AutoSlugField
13 12
 AutoSlugField = AutoSlugField
14 13
 
15 14
 
15
+# https://github.com/django/django/blob/64200c14e0072ba0ffef86da46b2ea82fd1e019a/django/db/models/fields/subclassing.py#L31-L44
16
+class Creator(object):
17
+    """
18
+    A placeholder class that provides a way to set the attribute on the model.
19
+    """
20
+    def __init__(self, field):
21
+        self.field = field
22
+
23
+    def __get__(self, obj, type=None):
24
+        if obj is None:
25
+            return self
26
+        return obj.__dict__[self.field.name]
27
+
28
+    def __set__(self, obj, value):
29
+        obj.__dict__[self.field.name] = self.field.to_python(value)
30
+
31
+
16 32
 class ExtendedURLField(CharField):
17 33
     description = _("URL")
18 34
 
@@ -64,7 +80,7 @@ class PositiveDecimalField(DecimalField):
64 80
         return super(PositiveDecimalField, self).formfield(min_value=0)
65 81
 
66 82
 
67
-class UppercaseCharField(six.with_metaclass(SubfieldBase, CharField)):
83
+class UppercaseCharField(CharField):
68 84
     """
69 85
     A simple subclass of ``django.db.models.fields.CharField`` that
70 86
     restricts all text to be uppercase.
@@ -73,6 +89,14 @@ class UppercaseCharField(six.with_metaclass(SubfieldBase, CharField)):
73 89
     https://docs.djangoproject.com/en/1.6/howto/custom-model-fields/#the-subfieldbase-metaclass  # NOQA
74 90
     """
75 91
 
92
+    def contribute_to_class(self, cls, name, **kwargs):
93
+        super(UppercaseCharField, self).contribute_to_class(
94
+            cls, name, **kwargs)
95
+        setattr(cls, self.name, Creator(self))
96
+
97
+    def from_db_value(self, value, expression, connection, context):
98
+        return self.to_python(value)
99
+
76 100
     def to_python(self, value):
77 101
         val = super(UppercaseCharField, self).to_python(value)
78 102
         if isinstance(val, six.string_types):
@@ -81,7 +105,7 @@ class UppercaseCharField(six.with_metaclass(SubfieldBase, CharField)):
81 105
             return val
82 106
 
83 107
 
84
-class NullCharField(six.with_metaclass(SubfieldBase, CharField)):
108
+class NullCharField(CharField):
85 109
     """
86 110
     CharField that stores '' as None and returns None as ''
87 111
     Useful when using unique=True and forms. Implies null==blank==True.
@@ -100,6 +124,13 @@ class NullCharField(six.with_metaclass(SubfieldBase, CharField)):
100 124
         kwargs['null'] = kwargs['blank'] = True
101 125
         super(NullCharField, self).__init__(*args, **kwargs)
102 126
 
127
+    def contribute_to_class(self, cls, name, **kwargs):
128
+        super(NullCharField, self).contribute_to_class(cls, name, **kwargs)
129
+        setattr(cls, self.name, Creator(self))
130
+
131
+    def from_db_value(self, value, expression, connection, context):
132
+        return self.to_python(value)
133
+
103 134
     def to_python(self, value):
104 135
         val = super(NullCharField, self).to_python(value)
105 136
         return val if val is not None else u''
@@ -118,7 +149,7 @@ class NullCharField(six.with_metaclass(SubfieldBase, CharField)):
118 149
         return name, path, args, kwargs
119 150
 
120 151
 
121
-class PhoneNumberField(six.with_metaclass(SubfieldBase, CharField)):
152
+class PhoneNumberField(CharField):
122 153
     """
123 154
     An international phone number.
124 155
 
@@ -149,6 +180,13 @@ class PhoneNumberField(six.with_metaclass(SubfieldBase, CharField)):
149 180
         kwargs['max_length'] = kwargs.get('max_length', 128)
150 181
         super(PhoneNumberField, self).__init__(*args, **kwargs)
151 182
 
183
+    def contribute_to_class(self, cls, name, **kwargs):
184
+        super(PhoneNumberField, self).contribute_to_class(cls, name, **kwargs)
185
+        setattr(cls, self.name, Creator(self))
186
+
187
+    def from_db_value(self, value, expression, connection, context):
188
+        return self.to_python(value)
189
+
152 190
     def get_prep_value(self, value):
153 191
         """
154 192
         Returns field's value prepared for saving into a database.

Loading…
Cancel
Save