Ticket #3148: 3148-propertyfield2.diff
File 3148-propertyfield2.diff, 5.9 KB (added by , 13 years ago) |
---|
-
django/db/models/fields/__init__.py
=== modified file 'django/db/models/fields/__init__.py'
old new 1183 1183 } 1184 1184 defaults.update(kwargs) 1185 1185 return super(URLField, self).formfield(**defaults) 1186 1187 def property_field(field): 1188 class PropertyField(property): 1189 """property subclass to be used to "wrap" another Field, not a true Field per-se""" 1190 1191 def __init__(self, fget=None, fset=None, fdel=None, doc=None): 1192 super(PropertyField, self).__init__(fget, fset, fdel, doc) 1193 self.field = field 1194 self.creation_counter = Field.creation_counter 1195 Field.creation_counter += 1 1196 1197 def __getattr__(self, name): 1198 return getattr(self.field, name) 1199 1200 def contribute_to_class(self, cls, name): 1201 self.name = name 1202 cls._meta.add_property_field(self) 1203 setattr(cls, name, self) 1204 1205 return PropertyField 1206 1207 1208 No newline at end of file -
django/db/models/options.py
=== modified file 'django/db/models/options.py'
old new 170 170 171 171 def add_virtual_field(self, field): 172 172 self.virtual_fields.append(field) 173 174 def add_property_field(self, f): 175 """ 176 Remove the original field wrapped by the property, and call again the field's 177 contribute_to_class 178 """ 179 if f.rel and isinstance(f.rel, ManyToManyRel): 180 inner_rel = filter(lambda x: x.name == f.field.name, self.local_many_to_many) 181 for r in inner_rel: 182 self.local_many_to_many.remove(r) 183 else: 184 inner_fields = filter(lambda x: x.name == f.field.name, self.local_fields) 185 for i_f in inner_fields: 186 self.local_fields.remove(i_f) 187 188 # hack needed to pass the unbound methods' type checking 189 num_parents = len(type(f).__bases__) 190 type(f).__bases__ += (type(f.field),) 191 type(f.field).contribute_to_class(f, f.model, f.name) 192 type(f).__bases__ = type(f).__bases__[:num_parents] 173 193 174 194 def setup_pk(self, field): 175 195 if not self.pk and field.primary_key: -
tests/regressiontests/model_fields/models.py
=== modified file 'tests/regressiontests/model_fields/models.py'
old new 15 15 16 16 from django.core.files.storage import FileSystemStorage 17 17 from django.db import models 18 from django.db.models.fields import property_field 18 19 from django.db.models.fields.files import ImageFieldFile, ImageField 19 20 20 21 … … 66 67 bfield = models.BooleanField() 67 68 string = models.CharField(max_length=10, default='abc') 68 69 70 class FooGetSet(models.Model): 71 _s = models.SlugField(max_length=255) 72 _c = models.CharField(max_length=255) 73 74 @property_field(_s) 75 def s(self): 76 return self._s 77 @s.setter 78 def s(self, value): 79 if value is "not_acceptable": 80 raise ValueError("not acceptable") 81 self._s = value 82 83 84 class GetSetSubclass(FooGetSet): 85 @property_field(filter(lambda x: x.name == "_c", FooGetSet._meta.fields)[0]) 86 def c(self): 87 return self._c[:-15] 88 89 @c.setter 90 def c(self, value): 91 self._c = value + " useless foobar" 92 93 class GetSetRel(models.Model): 94 _foos = models.ManyToManyField(FooGetSet) 95 96 @property_field(_foos) 97 def foos(self): 98 return self._foos 99 100 @foos.setter 101 def foos(self, values): 102 self._foos = [FooGetSet.objects.get_or_create(s=val)[0] for val in values] 103 69 104 ############################################################################### 70 105 # FileField 71 106 -
tests/regressiontests/model_fields/tests.py
=== modified file 'tests/regressiontests/model_fields/tests.py'
old new 8 8 from django.db.models.fields.files import FieldFile 9 9 from django.utils import unittest 10 10 11 from models import Foo, Bar, Whiz, BigD, BigS, Image, BigInt, Post, NullBooleanModel, BooleanModel, Document 11 from models import Foo, Bar, Whiz, BigD, BigS, Image, BigInt, Post, NullBooleanModel, BooleanModel, Document, FooGetSet, GetSetSubclass, GetSetRel 12 12 13 13 # If PIL available, do these tests. 14 14 if Image: … … 317 317 def test_lookup_integer_in_textfield(self): 318 318 self.assertEqual(Post.objects.filter(body=24).count(), 0) 319 319 320 class FieldProperties(test.TestCase): 321 def test_get_set(self): 322 """ 323 Test basic property functionality of a SlugField 324 """ 325 f = FooGetSet(s="test") 326 self.assertEqual(f.s, "test") 327 f.s = "test2" 328 self.assertEqual(f.s, "test2") 329 330 def set_non_acceptable(): 331 f.s = "not_acceptable" 332 self.assertRaises(ValueError, set_non_acceptable) 333 self.assertEqual(f.s, "test2") 334 335 f.save() 336 f = FooGetSet.objects.get(pk=f.pk) 337 self.assertEqual(f.s, "test2") 338 339 def test_inheritance(self): 340 """ 341 Test a property that's working on an inherited field 342 """ 343 sub = GetSetSubclass(s="foo", c="bar") 344 345 self.assertEqual(sub._c, "bar useless foobar") 346 self.assertEqual(sub.c, "bar") 347 348 def test_m2m(self): 349 """ 350 Test a property that's working on a many to many relationship 351 """ 352 r = GetSetRel() 353 r.save() 354 355 r.foos = ["a", "b", "c", "d"] 356 self.assertEqual(len(r.foos.all()), 4) 357 358 self.assertTrue(r in FooGetSet.objects.get(s="a").getsetrel_set.all()) 359 320 360 class FileFieldTests(unittest.TestCase): 321 361 def test_clearable(self): 322 362 """