Changeset 7600
- Timestamp:
- 06/09/08 09:03:35 (6 months ago)
- Files:
-
- django/trunk/django/core/serializers/base.py (modified) (1 diff)
- django/trunk/django/db/models/base.py (modified) (1 diff)
- django/trunk/django/db/models/options.py (modified) (1 diff)
- django/trunk/docs/serialization.txt (modified) (1 diff)
- django/trunk/tests/modeltests/model_inheritance/models.py (modified) (1 diff)
- django/trunk/tests/regressiontests/model_inheritance_regress (added)
- django/trunk/tests/regressiontests/model_inheritance_regress/__init__.py (added)
- django/trunk/tests/regressiontests/model_inheritance_regress/models.py (added)
- django/trunk/tests/regressiontests/serializers_regress/models.py (modified) (1 diff)
- django/trunk/tests/regressiontests/serializers_regress/tests.py (modified) (11 diffs)
Legend:
- Unmodified
- Added
- Removed
- Modified
- Copied
- Moved
django/trunk/django/core/serializers/base.py
r7477 r7600 39 39 for obj in queryset: 40 40 self.start_object(obj) 41 for field in obj._meta. fields:41 for field in obj._meta.local_fields: 42 42 if field.serialize: 43 43 if field.rel is None: django/trunk/django/db/models/base.py
r7526 r7600 291 291 signal = False 292 292 293 for parent, field in meta.parents.items(): 294 self.save_base(raw, parent) 295 setattr(self, field.attname, self._get_pk_val(parent._meta)) 293 # If we are in a raw save, save the object exactly as presented. 294 # That means that we don't try to be smart about saving attributes 295 # that might have come from the parent class - we just save the 296 # attributes we have been given to the class we have been given. 297 if not raw: 298 for parent, field in meta.parents.items(): 299 self.save_base(raw, parent) 300 setattr(self, field.attname, self._get_pk_val(parent._meta)) 296 301 297 302 non_pks = [f for f in meta.local_fields if not f.primary_key] 298 303 299 304 # First, try an UPDATE. If that doesn't update anything, do an INSERT. 300 305 pk_val = self._get_pk_val(meta) django/trunk/django/db/models/options.py
r7585 r7600 103 103 field = self.parents.value_for_index(0) 104 104 field.primary_key = True 105 self. pk = field105 self.setup_pk(field) 106 106 else: 107 107 auto = AutoField(verbose_name='ID', primary_key=True, django/trunk/docs/serialization.txt
r7548 r7600 63 63 doesn't specify all the fields that are required by a model, the deserializer 64 64 will not be able to save deserialized instances. 65 66 Inherited Models 67 ~~~~~~~~~~~~~~~~ 68 69 If you have a model that is defined using an `abstract base class`_, you don't 70 have to do anything special to serialize that model. Just call the serializer 71 on the object (or objects) that you want to serialize, and the output will be 72 a complete representation of the serialized object. 73 74 However, if you have a model that uses `multi-table inheritance`_, you also 75 need to serialize all of the base classes for the model. This is because only 76 the fields that are locally defined on the model will be serialized. For 77 example, consider the following models:: 78 79 class Place(models.Model): 80 name = models.CharField(max_length=50) 81 82 class Restaurant(Place): 83 serves_hot_dogs = models.BooleanField() 84 85 If you only serialize the Restaurant model:: 86 87 data = serializers.serialize('xml', Restaurant.objects.all()) 88 89 the fields on the serialized output will only contain the `serves_hot_dogs` 90 attribute. The `name` attribute of the base class will be ignored. 91 92 In order to fully serialize your Restaurant instances, you will need to 93 serialize the Place models as well:: 94 95 all_objects = list(Restaurant.objects.all()) + list(Place.objects.all()) 96 data = serializers.serialize('xml', all_objects) 97 98 .. _abstract base class: http://www.djangoproject.com/documentation/model-api/#abstract-base-classes 99 .. _multi-table inheritance: http://www.djangoproject.com/documentation/model-api/#multi-table-inheritance 65 100 66 101 Deserializing data django/trunk/tests/modeltests/model_inheritance/models.py
r7477 r7600 148 148 >>> ir = ItalianRestaurant(name='Ristorante Miron', address='1234 W. Ash', serves_hot_dogs=False, serves_pizza=False, serves_gnocchi=True, rating=4, chef=c) 149 149 >>> ir.save() 150 >>> ItalianRestaurant.objects.filter(address='1234 W. Ash') 151 [<ItalianRestaurant: Ristorante Miron the italian restaurant>] 152 150 153 >>> ir.address = '1234 W. Elm' 151 154 >>> ir.save() 155 >>> ItalianRestaurant.objects.filter(address='1234 W. Elm') 156 [<ItalianRestaurant: Ristorante Miron the italian restaurant>] 152 157 153 158 # Make sure Restaurant and ItalianRestaurant have the right fields in the right django/trunk/tests/regressiontests/serializers_regress/models.py
r7477 r7600 224 224 self.data = 666 225 225 super(ModifyingSaveData, self).save(raw) 226 227 # Tests for serialization of models using inheritance. 228 # Regression for #7202, #7350 229 class AbstractBaseModel(models.Model): 230 parent_data = models.IntegerField() 231 class Meta: 232 abstract = True 233 234 class InheritAbstractModel(AbstractBaseModel): 235 child_data = models.IntegerField() 236 237 class BaseModel(models.Model): 238 parent_data = models.IntegerField() 239 240 class InheritBaseModel(BaseModel): 241 child_data = models.IntegerField() 242 243 class ExplicitInheritBaseModel(BaseModel): 244 parent = models.OneToOneField(BaseModel) 245 child_data = models.IntegerField() django/trunk/tests/regressiontests/serializers_regress/tests.py
r7477 r7600 33 33 instance.data = data 34 34 models.Model.save_base(instance, raw=True) 35 return instance35 return [instance] 36 36 37 37 def generic_create(pk, klass, data): … … 41 41 for tag in data[1:]: 42 42 instance.tags.create(data=tag) 43 return instance43 return [instance] 44 44 45 45 def fk_create(pk, klass, data): … … 47 47 setattr(instance, 'data_id', data) 48 48 models.Model.save_base(instance, raw=True) 49 return instance49 return [instance] 50 50 51 51 def m2m_create(pk, klass, data): … … 53 53 models.Model.save_base(instance, raw=True) 54 54 instance.data = data 55 return instance55 return [instance] 56 56 57 57 def o2o_create(pk, klass, data): … … 59 59 instance.data_id = data 60 60 models.Model.save_base(instance, raw=True) 61 return instance61 return [instance] 62 62 63 63 def pk_create(pk, klass, data): … … 65 65 instance.data = data 66 66 models.Model.save_base(instance, raw=True) 67 return instance 68 67 return [instance] 68 69 def inherited_create(pk, klass, data): 70 instance = klass(id=pk,**data) 71 # This isn't a raw save because: 72 # 1) we're testing inheritance, not field behaviour, so none 73 # of the field values need to be protected. 74 # 2) saving the child class and having the parent created 75 # automatically is easier than manually creating both. 76 models.Model.save(instance) 77 created = [instance] 78 for klass,field in instance._meta.parents.items(): 79 created.append(klass.objects.get(id=pk)) 80 return created 81 69 82 # A set of functions that can be used to compare 70 83 # test data objects of various kinds … … 95 108 testcase.assertEqual(data, instance.data) 96 109 110 def inherited_compare(testcase, pk, klass, data): 111 instance = klass.objects.get(id=pk) 112 for key,value in data.items(): 113 testcase.assertEqual(value, getattr(instance,key)) 114 97 115 # Define some data types. Each data type is 98 116 # actually a pair of functions; one to create … … 104 122 o2o_obj = (o2o_create, o2o_compare) 105 123 pk_obj = (pk_create, pk_compare) 124 inherited_obj = (inherited_create, inherited_compare) 106 125 107 126 test_data = [ … … 256 275 (data_obj, 800, AutoNowDateTimeData, datetime.datetime(2006,6,16,10,42,37)), 257 276 (data_obj, 810, ModifyingSaveData, 42), 277 278 (inherited_obj, 900, InheritAbstractModel, {'child_data':37,'parent_data':42}), 279 (inherited_obj, 910, ExplicitInheritBaseModel, {'child_data':37,'parent_data':42}), 280 (inherited_obj, 920, InheritBaseModel, {'child_data':37,'parent_data':42}), 258 281 ] 259 282 … … 278 301 # Create all the objects defined in the test data 279 302 objects = [] 303 instance_count = {} 280 304 transaction.enter_transaction_management() 281 305 transaction.managed(True) 282 306 for (func, pk, klass, datum) in test_data: 283 objects.append(func[0](pk, klass, datum)) 307 objects.extend(func[0](pk, klass, datum)) 308 instance_count[klass] = 0 284 309 transaction.commit() 285 310 transaction.leave_transaction_management() 286 311 312 # Get a count of the number of objects created for each class 313 for klass in instance_count: 314 instance_count[klass] = klass.objects.count() 315 287 316 # Add the generic tagged objects to the object list 288 317 objects.extend(Tag.objects.all()) … … 305 334 func[1](self, pk, klass, datum) 306 335 336 # Assert that the number of objects deserialized is the 337 # same as the number that was serialized. 338 for klass, count in instance_count.items(): 339 self.assertEquals(count, klass.objects.count()) 340 307 341 def fieldsTest(format, self): 308 342 # Clear the database first
