mirror of
				https://github.com/django/django.git
				synced 2025-10-31 09:41:08 +00:00 
			
		
		
		
	Fixed #3741 -- Fixed serialization of GenericRelations. Thanks for the report, Alexander Solovyov.
git-svn-id: http://code.djangoproject.com/svn/django/trunk@4752 bcc190cf-cafb-0310-a4f2-bffc1f526a37
This commit is contained in:
		| @@ -34,17 +34,17 @@ class Serializer(object): | ||||
|         for obj in queryset: | ||||
|             self.start_object(obj) | ||||
|             for field in obj._meta.fields: | ||||
|                 if field is obj._meta.pk: | ||||
|                     continue | ||||
|                 elif field.rel is None: | ||||
|                     if self.selected_fields is None or field.attname in self.selected_fields: | ||||
|                         self.handle_field(obj, field) | ||||
|                 else: | ||||
|                     if self.selected_fields is None or field.attname[:-3] in self.selected_fields: | ||||
|                         self.handle_fk_field(obj, field) | ||||
|                 if field.serialize: | ||||
|                     if field.rel is None: | ||||
|                         if self.selected_fields is None or field.attname in self.selected_fields: | ||||
|                             self.handle_field(obj, field) | ||||
|                     else: | ||||
|                         if self.selected_fields is None or field.attname[:-3] in self.selected_fields: | ||||
|                             self.handle_fk_field(obj, field) | ||||
|             for field in obj._meta.many_to_many: | ||||
|                 if self.selected_fields is None or field.attname in self.selected_fields: | ||||
|                     self.handle_m2m_field(obj, field) | ||||
|                 if field.serialize: | ||||
|                     if self.selected_fields is None or field.attname in self.selected_fields: | ||||
|                         self.handle_m2m_field(obj, field) | ||||
|             self.end_object(obj) | ||||
|         self.end_serialization() | ||||
|         return self.getvalue() | ||||
|   | ||||
| @@ -67,7 +67,7 @@ class Field(object): | ||||
|  | ||||
|     def __init__(self, verbose_name=None, name=None, primary_key=False, | ||||
|         maxlength=None, unique=False, blank=False, null=False, db_index=False, | ||||
|         core=False, rel=None, default=NOT_PROVIDED, editable=True, | ||||
|         core=False, rel=None, default=NOT_PROVIDED, editable=True, serialize=True, | ||||
|         prepopulate_from=None, unique_for_date=None, unique_for_month=None, | ||||
|         unique_for_year=None, validator_list=None, choices=None, radio_admin=None, | ||||
|         help_text='', db_column=None): | ||||
| @@ -78,6 +78,7 @@ class Field(object): | ||||
|         self.blank, self.null = blank, null | ||||
|         self.core, self.rel, self.default = core, rel, default | ||||
|         self.editable = editable | ||||
|         self.serialize = serialize | ||||
|         self.validator_list = validator_list or [] | ||||
|         self.prepopulate_from = prepopulate_from | ||||
|         self.unique_for_date, self.unique_for_month = unique_for_date, unique_for_month | ||||
|   | ||||
| @@ -94,6 +94,7 @@ class GenericRelation(RelatedField, Field): | ||||
|          | ||||
|         kwargs['blank'] = True | ||||
|         kwargs['editable'] = False | ||||
|         kwargs['serialize'] = False | ||||
|         Field.__init__(self, **kwargs) | ||||
|  | ||||
|     def get_manipulator_field_objs(self): | ||||
|   | ||||
| @@ -84,6 +84,7 @@ class Options(object): | ||||
|             self.fields.insert(bisect(self.fields, field), field) | ||||
|             if not self.pk and field.primary_key: | ||||
|                 self.pk = field | ||||
|                 field.serialize = False | ||||
|  | ||||
|     def __repr__(self): | ||||
|         return '<Options for %s>' % self.object_name | ||||
|   | ||||
| @@ -6,6 +6,7 @@ This class sets up a model for each model field type | ||||
| """ | ||||
|  | ||||
| from django.db import models | ||||
| from django.contrib.contenttypes.models import ContentType | ||||
|  | ||||
| # The following classes are for testing basic data  | ||||
| # marshalling, including NULL values. | ||||
| @@ -73,6 +74,22 @@ class USStateData(models.Model): | ||||
| class XMLData(models.Model): | ||||
|     data = models.XMLField(null=True) | ||||
|      | ||||
| class Tag(models.Model): | ||||
|     """A tag on an item.""" | ||||
|     data = models.SlugField() | ||||
|     content_type = models.ForeignKey(ContentType) | ||||
|     object_id = models.PositiveIntegerField() | ||||
|  | ||||
|     content_object = models.GenericForeignKey() | ||||
|  | ||||
|     class Meta: | ||||
|         ordering = ["data"] | ||||
|  | ||||
| class GenericData(models.Model): | ||||
|     data = models.CharField(maxlength=30) | ||||
|  | ||||
|     tags = models.GenericRelation(Tag) | ||||
|      | ||||
| # The following test classes are all for validation | ||||
| # of related objects; in particular, forward, backward, | ||||
| # and self references. | ||||
|   | ||||
| @@ -25,6 +25,14 @@ def data_create(pk, klass, data): | ||||
|     instance.save()     | ||||
|     return instance | ||||
|  | ||||
| def generic_create(pk, klass, data): | ||||
|     instance = klass(id=pk) | ||||
|     instance.data = data[0] | ||||
|     instance.save() | ||||
|     for tag in data[1:]: | ||||
|         instance.tags.create(data=tag) | ||||
|     return instance | ||||
|      | ||||
| def fk_create(pk, klass, data): | ||||
|     instance = klass(id=pk) | ||||
|     setattr(instance, 'data_id', data) | ||||
| @@ -56,6 +64,11 @@ def data_compare(testcase, pk, klass, data): | ||||
|     testcase.assertEqual(data, instance.data,  | ||||
|                          "Objects with PK=%d not equal; expected '%s' (%s), got '%s' (%s)" % (pk,data, type(data), instance.data, type(instance.data))) | ||||
|  | ||||
| def generic_compare(testcase, pk, klass, data): | ||||
|     instance = klass.objects.get(id=pk) | ||||
|     testcase.assertEqual(data[0], instance.data) | ||||
|     testcase.assertEqual(data[1:], [t.data for t in instance.tags.all()]) | ||||
|      | ||||
| def fk_compare(testcase, pk, klass, data): | ||||
|     instance = klass.objects.get(id=pk) | ||||
|     testcase.assertEqual(data, instance.data_id) | ||||
| @@ -76,6 +89,7 @@ def pk_compare(testcase, pk, klass, data): | ||||
| # actually a pair of functions; one to create | ||||
| # and one to compare objects of that type | ||||
| data_obj = (data_create, data_compare) | ||||
| generic_obj = (generic_create, generic_compare) | ||||
| fk_obj = (fk_create, fk_compare) | ||||
| m2m_obj = (m2m_create, m2m_compare) | ||||
| o2o_obj = (o2o_create, o2o_compare) | ||||
| @@ -140,6 +154,9 @@ The end."""), | ||||
|     (data_obj, 190, XMLData, "<foo></foo>"), | ||||
|     (data_obj, 191, XMLData, None), | ||||
|  | ||||
|     (generic_obj, 200, GenericData, ['Generic Object 1', 'tag1', 'tag2']), | ||||
|     (generic_obj, 201, GenericData, ['Generic Object 2', 'tag2', 'tag3']), | ||||
|  | ||||
|     (data_obj, 300, Anchor, "Anchor 1"), | ||||
|     (data_obj, 301, Anchor, "Anchor 2"), | ||||
|  | ||||
| @@ -222,6 +239,9 @@ def serializerTest(format, self): | ||||
|     transaction.commit() | ||||
|     transaction.leave_transaction_management() | ||||
|  | ||||
|     # Add the generic tagged objects to the object list  | ||||
|     objects.extend(Tag.objects.all()) | ||||
|      | ||||
|     # Serialize the test database | ||||
|     serialized_data = serializers.serialize(format, objects, indent=2) | ||||
|  | ||||
|   | ||||
		Reference in New Issue
	
	Block a user