From c0ad626dca67fe2e0c1dce3c5db524cfa77a9884 Mon Sep 17 00:00:00 2001 From: Jacob Kaplan-Moss Date: Thu, 9 Apr 2009 15:03:31 +0000 Subject: [PATCH] Fixed #10647: intermediary tables between two umanaged models are no longer created. git-svn-id: http://code.djangoproject.com/svn/django/trunk@10455 bcc190cf-cafb-0310-a4f2-bffc1f526a37 --- django/db/backends/creation.py | 3 ++- docs/ref/models/options.txt | 15 +++++++++----- tests/modeltests/unmanaged_models/models.py | 21 ++++++++++++++++++++ tests/modeltests/unmanaged_models/tests.py | 22 +++++++++++++++++++++ 4 files changed, 55 insertions(+), 6 deletions(-) create mode 100644 tests/modeltests/unmanaged_models/tests.py diff --git a/django/db/backends/creation.py b/django/db/backends/creation.py index b338a342ef..f6041c73f3 100644 --- a/django/db/backends/creation.py +++ b/django/db/backends/creation.py @@ -140,7 +140,8 @@ class BaseDatabaseCreation(object): "Return the CREATE TABLE statments for all the many-to-many tables defined on a model" output = [] for f in model._meta.local_many_to_many: - output.extend(self.sql_for_many_to_many_field(model, f, style)) + if model._meta.managed or f.rel.to._meta.managed: + output.extend(self.sql_for_many_to_many_field(model, f, style)) return output def sql_for_many_to_many_field(self, model, f, style): diff --git a/docs/ref/models/options.txt b/docs/ref/models/options.txt index 35e52e08ac..8402567f7a 100644 --- a/docs/ref/models/options.txt +++ b/docs/ref/models/options.txt @@ -98,11 +98,16 @@ model handling are exactly the same as normal. This includes specify all the columns from the database table you are modeling when using unmanaged models. - 2. If a model contains a :class:`~django.db.models.ManyToManyField` and - has ``managed=False``, the intermediate table for the many-to-many join - will also not be created. Should you require the intermediate table to - be created, set it up as an explicit model and use the - :attr:`ManyToManyField.through` attribute. + 2. If a model with ``managed=False`` contains a + :class:`~django.db.models.ManyToManyField` that points to another + unmanaged model, then the intermediate table for the many-to-many join + will also not be created. However, a the intermediary table between one + managed and one unmanaged model *will* be created. + + If you need to change this default behavior, create the intermediary + table as an explicit model (with ``managed`` set as needed) and use the + :attr:`ManyToManyField.through` attribute to make the relation use your + custom model. For tests involving models with ``managed=False``, it's up to you to ensure the correct tables are created as part of the test setup. diff --git a/tests/modeltests/unmanaged_models/models.py b/tests/modeltests/unmanaged_models/models.py index 717c8d5b3a..4402090582 100644 --- a/tests/modeltests/unmanaged_models/models.py +++ b/tests/modeltests/unmanaged_models/models.py @@ -89,6 +89,27 @@ class Intermediate(models.Model): db_table = 'D01' managed = False +# +# These next models test the creation (or not) of many to many join tables +# between managed and unmanaged models. A join table between two unmanaged +# models shouldn't be automatically created (see #10647). +# +class Unmanaged1(models.Model): + class Meta: + managed = False + +# Unmanged with an m2m to unmanaged: the intermediary table won't be created. +class Unmanaged2(models.Model): + mm = models.ManyToManyField(Unmanaged1) + + class Meta: + managed = False + +# Here's an unmanaged model with an m2m to a managed one; the intermediary +# table *will* be created (unless given a custom `through` as for C02 above). +class Managed1(models.Model): + mm = models.ManyToManyField(Unmanaged1) + __test__ = {'API_TESTS':""" The main test here is that the all the models can be created without any database errors. We can also do some more simple insertion and lookup tests diff --git a/tests/modeltests/unmanaged_models/tests.py b/tests/modeltests/unmanaged_models/tests.py new file mode 100644 index 0000000000..c5f14bd3df --- /dev/null +++ b/tests/modeltests/unmanaged_models/tests.py @@ -0,0 +1,22 @@ +from django.test import TestCase +from django.db import connection +from models import Unmanaged1, Unmanaged2, Managed1 + +class ManyToManyUnmanagedTests(TestCase): + + def test_many_to_many_between_unmanaged(self): + """ + The intermediary table between two unmanaged models should not be created. + """ + table = Unmanaged2._meta.get_field('mm').m2m_db_table() + tables = connection.introspection.table_names() + self.assert_(table not in tables, "Table '%s' should not exist, but it does." % table) + + def test_many_to_many_between_unmanaged_and_managed(self): + """ + An intermediary table between a managed and an unmanaged model should be created. + """ + table = Managed1._meta.get_field('mm').m2m_db_table() + tables = connection.introspection.table_names() + self.assert_(table in tables, "Table '%s' does not exist." % table) + \ No newline at end of file