Kaydet (Commit) 52edc160 authored tarafından Andrew Godwin's avatar Andrew Godwin

Add more stringent M2M tests and fix the bug they exposed

üst 5b522cd8
......@@ -9,7 +9,7 @@ from django.conf import settings
from django.db.models.fields.related import ManyToManyRel
from django.db.models.fields import AutoField, FieldDoesNotExist
from django.db.models.fields.proxy import OrderWrt
from django.db.models.loading import get_models, app_cache_ready, cache
from django.db.models.loading import app_cache_ready, cache
from django.utils import six
from django.utils.functional import cached_property
from django.utils.encoding import force_text, smart_text, python_2_unicode_compatible
......@@ -495,7 +495,7 @@ class Options(object):
cache[obj] = model
# Collect also objects which are in relation to some proxy child/parent of self.
proxy_cache = cache.copy()
for klass in get_models(include_auto_created=True, only_installed=False):
for klass in self.app_cache.get_models(include_auto_created=True, only_installed=False):
if not klass._meta.swapped:
for f in klass._meta.local_fields:
if f.rel and not isinstance(f.rel.to, six.string_types) and f.generate_reverse_relation:
......@@ -538,7 +538,7 @@ class Options(object):
cache[obj] = parent
else:
cache[obj] = model
for klass in get_models(only_installed=False):
for klass in self.app_cache.get_models(only_installed=False):
if not klass._meta.swapped:
for f in klass._meta.local_many_to_many:
if (f.rel
......
......@@ -116,7 +116,7 @@ class OperationTests(MigrationTestBase):
"""
project_state = self.set_up_test_model("test_adflmm", second_model=True)
# Test the state alteration
operation = migrations.AddField("Pony", "stables", models.ManyToManyField("Stable"))
operation = migrations.AddField("Pony", "stables", models.ManyToManyField("Stable", related_name="ponies"))
new_state = project_state.clone()
operation.state_forwards("test_adflmm", new_state)
self.assertEqual(len(new_state.models["test_adflmm", "pony"].fields), 4)
......@@ -126,6 +126,13 @@ class OperationTests(MigrationTestBase):
operation.database_forwards("test_adflmm", editor, project_state, new_state)
self.assertTableExists("test_adflmm_pony_stables")
self.assertColumnNotExists("test_adflmm_pony", "stables")
# Make sure the M2M field actually works
app_cache = new_state.render()
Pony = app_cache.get_model("test_adflmm", "Pony")
p = Pony.objects.create(pink=False, weight=4.55)
p.stables.create()
self.assertEqual(p.stables.count(), 1)
p.stables.all().delete()
# And test reversal
with connection.schema_editor() as editor:
operation.database_backwards("test_adflmm", editor, new_state, project_state)
......
......@@ -37,7 +37,7 @@ class BookWithM2M(models.Model):
author = models.ForeignKey(Author)
title = models.CharField(max_length=100, db_index=True)
pub_date = models.DateTimeField()
tags = models.ManyToManyField("Tag", related_name="books")
tags = models.ManyToManyField("TagM2MTest", related_name="books")
class Meta:
app_cache = new_app_cache
......@@ -62,6 +62,14 @@ class Tag(models.Model):
app_cache = new_app_cache
class TagM2MTest(models.Model):
title = models.CharField(max_length=255)
slug = models.SlugField(unique=True)
class Meta:
app_cache = new_app_cache
class TagIndexed(models.Model):
title = models.CharField(max_length=255)
slug = models.SlugField(unique=True)
......
......@@ -6,7 +6,7 @@ from django.db import connection, DatabaseError, IntegrityError
from django.db.models.fields import IntegerField, TextField, CharField, SlugField
from django.db.models.fields.related import ManyToManyField, ForeignKey
from django.db.transaction import atomic
from .models import Author, AuthorWithM2M, Book, BookWithSlug, BookWithM2M, Tag, TagIndexed, TagUniqueRename, UniqueTest
from .models import Author, AuthorWithM2M, Book, BookWithSlug, BookWithM2M, Tag, TagIndexed, TagM2MTest, TagUniqueRename, UniqueTest
class SchemaTests(TransactionTestCase):
......@@ -20,7 +20,7 @@ class SchemaTests(TransactionTestCase):
available_apps = []
models = [Author, AuthorWithM2M, Book, BookWithSlug, BookWithM2M, Tag, TagUniqueRename, UniqueTest]
models = [Author, AuthorWithM2M, Book, BookWithSlug, BookWithM2M, Tag, TagIndexed, TagM2MTest, TagUniqueRename, UniqueTest]
no_table_strings = ["no such table", "unknown table", "does not exist"]
# Utility functions
......@@ -234,7 +234,7 @@ class SchemaTests(TransactionTestCase):
editor.create_model(BookWithM2M)
# Ensure there is now an m2m table there
columns = self.column_classes(BookWithM2M._meta.get_field_by_name("tags")[0].rel.through)
self.assertEqual(columns['tag_id'][0], "IntegerField")
self.assertEqual(columns['tagm2mtest_id'][0], "IntegerField")
def test_m2m(self):
"""
......@@ -243,9 +243,9 @@ class SchemaTests(TransactionTestCase):
# Create the tables
with connection.schema_editor() as editor:
editor.create_model(AuthorWithM2M)
editor.create_model(Tag)
editor.create_model(TagM2MTest)
# Create an M2M field
new_field = ManyToManyField("schema.Tag", related_name="authors")
new_field = ManyToManyField("schema.TagM2MTest", related_name="authors")
new_field.contribute_to_class(AuthorWithM2M, "tags")
try:
# Ensure there's no m2m table there
......@@ -258,7 +258,7 @@ class SchemaTests(TransactionTestCase):
)
# Ensure there is now an m2m table there
columns = self.column_classes(new_field.rel.through)
self.assertEqual(columns['tag_id'][0], "IntegerField")
self.assertEqual(columns['tagm2mtest_id'][0], "IntegerField")
# Remove the M2M table again
with connection.schema_editor() as editor:
editor.remove_field(
......@@ -279,17 +279,17 @@ class SchemaTests(TransactionTestCase):
with connection.schema_editor() as editor:
editor.create_model(Author)
editor.create_model(BookWithM2M)
editor.create_model(Tag)
editor.create_model(TagM2MTest)
editor.create_model(UniqueTest)
# Ensure the M2M exists and points to Tag
# Ensure the M2M exists and points to TagM2MTest
constraints = connection.introspection.get_constraints(connection.cursor(), BookWithM2M._meta.get_field_by_name("tags")[0].rel.through._meta.db_table)
if connection.features.supports_foreign_keys:
for name, details in constraints.items():
if details['columns'] == ["tag_id"] and details['foreign_key']:
self.assertEqual(details['foreign_key'], ('schema_tag', 'id'))
if details['columns'] == ["tagm2mtest_id"] and details['foreign_key']:
self.assertEqual(details['foreign_key'], ('schema_tagm2mtest', 'id'))
break
else:
self.fail("No FK constraint for tag_id found")
self.fail("No FK constraint for tagm2mtest_id found")
# Repoint the M2M
new_field = ManyToManyField(UniqueTest)
new_field.contribute_to_class(BookWithM2M, "uniques")
......@@ -310,7 +310,7 @@ class SchemaTests(TransactionTestCase):
self.assertEqual(details['foreign_key'], ('schema_uniquetest', 'id'))
break
else:
self.fail("No FK constraint for tag_id found")
self.fail("No FK constraint for uniquetest_id found")
finally:
# Cleanup model states
BookWithM2M._meta.local_many_to_many.remove(new_field)
......
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment