From 7b63d3d3b4fcf58070ced8e7a8c766cc93a26420 Mon Sep 17 00:00:00 2001 From: Russell Keith-Magee Date: Thu, 5 Nov 2009 11:57:28 +0000 Subject: [PATCH] Fixed #12168 -- Corrected the registration of m2m autocreated models when models.py is split into submodules. Thanks to Jens Diemer for the report and test case. git-svn-id: http://code.djangoproject.com/svn/django/trunk@11724 bcc190cf-cafb-0310-a4f2-bffc1f526a37 --- django/db/models/fields/related.py | 11 +++++- tests/modeltests/model_package/__init__.py | 1 + .../model_package/models/__init__.py | 3 ++ .../model_package/models/article.py | 10 ++++++ .../model_package/models/publication.py | 7 ++++ tests/modeltests/model_package/tests.py | 34 +++++++++++++++++++ 6 files changed, 65 insertions(+), 1 deletion(-) create mode 100644 tests/modeltests/model_package/__init__.py create mode 100644 tests/modeltests/model_package/models/__init__.py create mode 100644 tests/modeltests/model_package/models/article.py create mode 100644 tests/modeltests/model_package/models/publication.py create mode 100644 tests/modeltests/model_package/tests.py diff --git a/django/db/models/fields/related.py b/django/db/models/fields/related.py index e8a4b98481..c4bd9fb983 100644 --- a/django/db/models/fields/related.py +++ b/django/db/models/fields/related.py @@ -829,9 +829,18 @@ def create_many_to_many_intermediary_model(field, klass): 'auto_created': klass, 'unique_together': (from_, to) }) + # If the models have been split into subpackages, klass.__module__ + # will be the subpackge, not the models module for the app. (See #12168) + # Compose the actual models module name by stripping the trailing parts + # of the namespace until we find .models + parts = klass.__module__.split('.') + while parts[-1] != 'models': + parts.pop() + module = '.'.join(parts) + # Construct and return the new class. return type(name, (models.Model,), { 'Meta': meta, - '__module__': klass.__module__, + '__module__': module, from_: models.ForeignKey(klass, related_name='%s+' % name), to: models.ForeignKey(to_model, related_name='%s+' % name) }) diff --git a/tests/modeltests/model_package/__init__.py b/tests/modeltests/model_package/__init__.py new file mode 100644 index 0000000000..8b13789179 --- /dev/null +++ b/tests/modeltests/model_package/__init__.py @@ -0,0 +1 @@ + diff --git a/tests/modeltests/model_package/models/__init__.py b/tests/modeltests/model_package/models/__init__.py new file mode 100644 index 0000000000..91e1b02e7d --- /dev/null +++ b/tests/modeltests/model_package/models/__init__.py @@ -0,0 +1,3 @@ +# Import all the models from subpackages +from article import Article +from publication import Publication diff --git a/tests/modeltests/model_package/models/article.py b/tests/modeltests/model_package/models/article.py new file mode 100644 index 0000000000..c8fae1c72d --- /dev/null +++ b/tests/modeltests/model_package/models/article.py @@ -0,0 +1,10 @@ +from django.db import models +from django.contrib.sites.models import Site + +class Article(models.Model): + sites = models.ManyToManyField(Site) + headline = models.CharField(max_length=100) + publications = models.ManyToManyField("model_package.Publication", null=True, blank=True,) + + class Meta: + app_label = 'model_package' diff --git a/tests/modeltests/model_package/models/publication.py b/tests/modeltests/model_package/models/publication.py new file mode 100644 index 0000000000..4dc2d6a148 --- /dev/null +++ b/tests/modeltests/model_package/models/publication.py @@ -0,0 +1,7 @@ +from django.db import models + +class Publication(models.Model): + title = models.CharField(max_length=30) + + class Meta: + app_label = 'model_package' diff --git a/tests/modeltests/model_package/tests.py b/tests/modeltests/model_package/tests.py new file mode 100644 index 0000000000..6e8c158a68 --- /dev/null +++ b/tests/modeltests/model_package/tests.py @@ -0,0 +1,34 @@ +""" +>>> from models.publication import Publication +>>> from models.article import Article +>>> from django.contrib.auth.views import Site + +>>> p = Publication(title="FooBar") +>>> p.save() +>>> p + + +>>> from django.contrib.sites.models import Site +>>> current_site = Site.objects.get_current() +>>> current_site + + +# Regression for #12168: models split into subpackages still get M2M tables + +>>> a = Article(headline="a foo headline") +>>> a.save() +>>> a.publications.add(p) +>>> a.sites.add(current_site) +>>> a.save() + +>>> a = Article.objects.get(id=1) +>>> a + +>>> a.id +1 +>>> a.sites.count() +1 + +""" + +