#14226: Bug in dumpdata dependency calculation involving ManyToManyFields
---------------------------+------------------------------------------------
Reporter: aneil | Owner: nobody
Status: new | Milestone:
Component: Serialization | Version: 1.2
Keywords: | Stage: Unreviewed
Has_patch: 0 |
---------------------------+------------------------------------------------
The manage.py dumpdata command incorrectly interprets !ManyToMany
relationships as dependencies of the model that declares them (rather than
the other way around).
In the example below are 5 models - User, Tag and Posting, where both User
and Posting have M2M relationships to Tag via !UserTag and !PostingTag,
respectively. This should be serializable.
Here are the actual dependencies:
{{{
User: None
Tag: None
Posting: User
PostingTag: Posting, Tag
UserTag: User, Tag
}}}
However, dumpdata fails with this error:
Error: Can't resolve dependencies for main.Posting, main.!PostingTag,
main.Tag, main.User, main.!UserTag in serialized app list.
{{{
from django.db.models import
Model,CharField,ForeignKey,ManyToManyField,TextField,DateTimeField
class User(Model):
username = CharField(max_length=20)
password = CharField(max_length=20)
topics = ManyToManyField("Tag",through="UserTag")
def natural_key(self):
return (self.username,)
class Posting(Model):
user = ForeignKey(User)
text = TextField()
time = DateTimeField()
def natural_key(self):
return (self.user.username,self.time)
natural_key.dependencies=['main.User']
class Tag(Model):
name = CharField(max_length=20)
postings = ManyToManyField(Posting,through="PostingTag")
def natural_key(self):
return (self.name,)
class PostingTag(Model):
tag = ForeignKey(Tag)
posting = ForeignKey(Posting)
def natural_key(self):
return (self.tag.natural_key(),self.posting.natural_key())
class UserTag(Model):
user = ForeignKey(User)
tag = ForeignKey(Tag)
def natural_key(self):
return (self.tag.natural_key(),self.user.natural_key())
}}}
The reason this occurs is invalid logic in
django/core/management/commands/dumpdata.py in lines 152-155. Here is the
relevant code & context:
{{{
145 # Now add a dependency for any FK or M2M relation with
146 # a model that defines a natural key
147 for field in model._meta.fields:
148 if hasattr(field.rel, 'to'):
149 rel_model = field.rel.to
150 if hasattr(rel_model, 'natural_key'):
151 deps.append(rel_model)
152 for field in model._meta.many_to_many:
153 rel_model = field.rel.to
154 if hasattr(rel_model, 'natural_key'):
155 deps.append(rel_model)
156 model_dependencies.append((model, deps))
}}}
Lines 152-155 treat M2M relations like FK relations. This is incorrect.
A Model named by an FK is a dependency, however, the model named by an M2M
is not.
The fix requires adding the M2M *table* to the model_list, and processing
its dependencies accordingly.
I've attached a simple test project that demonstrates the problem.
--
Ticket URL: <http://code.djangoproject.com/ticket/14226>
Django <http://code.djangoproject.com/>
The Web framework for perfectionists with deadlines.
--
You received this message because you are subscribed to the Google Groups
"Django updates" group.
To post to this group, send email to [email protected].
To unsubscribe from this group, send email to
[email protected].
For more options, visit this group at
http://groups.google.com/group/django-updates?hl=en.