#11310 closed (worksforme)
Unable to serialize ManyToMany fields with "trough"
| Reported by: | Owned by: | nobody | |
|---|---|---|---|
| Component: | Core (Serialization) | Version: | dev |
| Severity: | Keywords: | ManyToMany | |
| Cc: | Triage Stage: | Unreviewed | |
| Has patch: | yes | Needs documentation: | no |
| Needs tests: | no | Patch needs improvement: | no |
| Easy pickings: | no | UI/UX: | no |
Description
Problem is, that ManyToMany field with intermediate table is ignored in PythonSerializer. This patch should fix it.
http://code.djangoproject.com/svn/django/trunk/django/core/serializers/python.py 59,61c59,60 < if field.creates_table: < self._current[field.name] = [smart_unicode(related._get_pk_val(), strings_only=True) < for related in getattr(obj, field.name).iterator()] --- > self._current[field.name] = [smart_unicode(related._get_pk_val(), strings_only=True) > for related in getattr(obj, field.name).iterator()]
Change History (6)
comment:1 by , 16 years ago
| Component: | Uncategorized → Serialization |
|---|---|
| Has patch: | set |
| Keywords: | ManyToMany added |
comment:2 by , 16 years ago
| Resolution: | → worksforme |
|---|---|
| Status: | new → closed |
comment:3 by , 16 years ago
| Resolution: | worksforme |
|---|---|
| Status: | closed → reopened |
| Version: | 1.0 → SVN |
Hi,
look at this example:
class A(models.Model):
foo = models.CharField(max_length=32)
# b = models.ManyToManyField('B', through='A_B')
b = models.ManyToManyField('B')
class B(models.Model):
bar = models.CharField(max_length=32)
class A_B(models.Model):
a = models.ForeignKey('A')
b = models.ForeignKey('B')
Then i run:
>>> from django.core.serializers import serialize
>>> serialize('python', A.objects.all())
[{'pk': 1L, 'model': u'testapp.a', 'fields': {'foo': u'eeeee', 'b': [1L]}}]
This is OK.
Now I change models to this:
class A(models.Model):
foo = models.CharField(max_length=32)
b = models.ManyToManyField('B', through='A_B')
# b = models.ManyToManyField('B')
class B(models.Model):
bar = models.CharField(max_length=32)
class A_B(models.Model):
a = models.ForeignKey('A')
b = models.ForeignKey('B')
I serialize it:
>>> from django.core.serializers import serialize
>>> serialize('python', A.objects.all())
[{'pk': 1L, 'model': u'testapp.a', 'fields': {'foo': u'eeeee'}}]
'b' is missing in output...
comment:4 by , 16 years ago
| Resolution: | → worksforme |
|---|---|
| Status: | reopened → closed |
Your example code is explicitly serializing objects of type A. However, when you have a through relationship, you need to serialize the A_B model separately, since that model could contain extra data.
When you don't have a through model, there isn't an actual model representing the through relationship., so the m2m data is included on the A model as a list of related objects.
comment:5 by , 16 years ago
Thanks for explanation. I was migrating some models without 'through' to use 'through' and serialization behaviour was changed. I made a wraparound of this using custom serializer:
class CustomSerializer(python.Serializer): def handle_m2m_field(self, obj, field): field.creates_table = True super(XMLRPCSerializer, self).handle_m2m_field(obj, field)
Yeah, it's ugly, but it works ;-)
The test suite contains a test to validate that serialization works for m2m with a through field (see the [http://code.djangoproject.com/browser/django/trunk/tests/regressiontests/m2m_through_regress/models.py regressiontests/m2m_through_regress tests). Without a test case showing a specific failure case I'm going to mark this worksforme.