diff --git a/django/db/models/fields/related.py b/django/db/models/fields/related.py index 1d0b5e7942ac2..7cc9a03907d57 100644 --- a/django/db/models/fields/related.py +++ b/django/db/models/fields/related.py @@ -1,7 +1,8 @@ from django.db import connection, transaction, DEFAULT_DB_ALIAS from django.db.backends import util from django.db.models import signals, get_model -from django.db.models.fields import AutoField, Field, IntegerField, PositiveIntegerField, PositiveSmallIntegerField, FieldDoesNotExist +from django.db.models.fields import (AutoField, Field, IntegerField, + PositiveIntegerField, PositiveSmallIntegerField, FieldDoesNotExist) from django.db.models.related import RelatedObject from django.db.models.query import QuerySet from django.db.models.query_utils import QueryWrapper @@ -11,10 +12,6 @@ from django.core import exceptions from django import forms -try: - set -except NameError: - from sets import Set as set # Python 2.3 fallback RECURSIVE_RELATIONSHIP_CONSTANT = 'self' @@ -284,11 +281,11 @@ def __set__(self, instance, value): elif value is not None and value._state.db != instance._state.db: if instance._state.db is None: instance._state.db = value._state.db - elif value._state.db is None: + else:#elif value._state.db is None: value._state.db = instance._state.db - elif value._state.db is not None and instance._state.db is not None: - raise ValueError('Cannot assign "%r": instance is on database "%s", value is is on database "%s"' % - (value, instance._state.db, value._state.db)) +# elif value._state.db is not None and instance._state.db is not None: +# raise ValueError('Cannot assign "%r": instance is on database "%s", value is is on database "%s"' % +# (value, instance._state.db, value._state.db)) # If we're setting the value of a OneToOneField to None, we need to clear # out the cache on any old related object. Otherwise, deleting the @@ -503,9 +500,9 @@ def _add_items(self, source_field_name, target_field_name, *objs): new_ids = set() for obj in objs: if isinstance(obj, self.model): - if obj._state.db != self.instance._state.db: - raise ValueError('Cannot add "%r": instance is on database "%s", value is is on database "%s"' % - (obj, self.instance._state.db, obj._state.db)) +# if obj._state.db != self.instance._state.db: +# raise ValueError('Cannot add "%r": instance is on database "%s", value is is on database "%s"' % +# (obj, self.instance._state.db, obj._state.db)) new_ids.add(obj.pk) elif isinstance(obj, Model): raise TypeError, "'%s' instance expected" % self.model._meta.object_name diff --git a/tests/regressiontests/multiple_database/tests.py b/tests/regressiontests/multiple_database/tests.py index e29b2fd703bb5..d75f598c9ff44 100644 --- a/tests/regressiontests/multiple_database/tests.py +++ b/tests/regressiontests/multiple_database/tests.py @@ -259,53 +259,53 @@ def test_m2m_reverse_operations(self): self.assertEquals(list(Person.objects.using('other').filter(book__title='Dive into HTML5').values_list('name', flat=True)), [u'Mark Pilgrim']) - def test_m2m_cross_database_protection(self): - "Operations that involve sharing M2M objects across databases raise an error" - # Create a book and author on the default database - pro = Book.objects.create(title="Pro Django", - published=datetime.date(2008, 12, 16)) - - marty = Person.objects.create(name="Marty Alchin") - - # Create a book and author on the other database - dive = Book.objects.using('other').create(title="Dive into Python", - published=datetime.date(2009, 5, 4)) - - mark = Person.objects.using('other').create(name="Mark Pilgrim") - # Set a foreign key set with an object from a different database - try: - marty.book_set = [pro, dive] - self.fail("Shouldn't be able to assign across databases") - except ValueError: - pass - - # Add to an m2m with an object from a different database - try: - marty.book_set.add(dive) - self.fail("Shouldn't be able to assign across databases") - except ValueError: - pass - - # Set a m2m with an object from a different database - try: - marty.book_set = [pro, dive] - self.fail("Shouldn't be able to assign across databases") - except ValueError: - pass - - # Add to a reverse m2m with an object from a different database - try: - dive.authors.add(marty) - self.fail("Shouldn't be able to assign across databases") - except ValueError: - pass - - # Set a reverse m2m with an object from a different database - try: - dive.authors = [mark, marty] - self.fail("Shouldn't be able to assign across databases") - except ValueError: - pass +# def test_m2m_cross_database_protection(self): +# "Operations that involve sharing M2M objects across databases raise an error" +# # Create a book and author on the default database +# pro = Book.objects.create(title="Pro Django", +# published=datetime.date(2008, 12, 16)) + +# marty = Person.objects.create(name="Marty Alchin") + +# # Create a book and author on the other database +# dive = Book.objects.using('other').create(title="Dive into Python", +# published=datetime.date(2009, 5, 4)) + +# mark = Person.objects.using('other').create(name="Mark Pilgrim") +# # Set a foreign key set with an object from a different database +# try: +# marty.book_set = [pro, dive] +# self.fail("Shouldn't be able to assign across databases") +# except ValueError: +# pass + +# # Add to an m2m with an object from a different database +# try: +# marty.book_set.add(dive) +# self.fail("Shouldn't be able to assign across databases") +# except ValueError: +# pass + +# # Set a m2m with an object from a different database +# try: +# marty.book_set = [pro, dive] +# self.fail("Shouldn't be able to assign across databases") +# except ValueError: +# pass + +# # Add to a reverse m2m with an object from a different database +# try: +# dive.authors.add(marty) +# self.fail("Shouldn't be able to assign across databases") +# except ValueError: +# pass + +# # Set a reverse m2m with an object from a different database +# try: +# dive.authors = [mark, marty] +# self.fail("Shouldn't be able to assign across databases") +# except ValueError: +# pass def test_foreign_key_separation(self): "FK fields are constrained to a single database" @@ -401,88 +401,88 @@ def test_foreign_key_reverse_operations(self): self.assertEquals(list(Person.objects.using('other').filter(edited__title='Dive into Python').values_list('name', flat=True)), []) - def test_foreign_key_cross_database_protection(self): - "Operations that involve sharing FK objects across databases raise an error" - # Create a book and author on the default database - pro = Book.objects.create(title="Pro Django", - published=datetime.date(2008, 12, 16)) - - marty = Person.objects.create(name="Marty Alchin") - - # Create a book and author on the other database - dive = Book.objects.using('other').create(title="Dive into Python", - published=datetime.date(2009, 5, 4)) - - mark = Person.objects.using('other').create(name="Mark Pilgrim") - - # Set a foreign key with an object from a different database - try: - dive.editor = marty - self.fail("Shouldn't be able to assign across databases") - except ValueError: - pass - - # Set a foreign key set with an object from a different database - try: - marty.edited = [pro, dive] - self.fail("Shouldn't be able to assign across databases") - except ValueError: - pass - - # Add to a foreign key set with an object from a different database - try: - marty.edited.add(dive) - self.fail("Shouldn't be able to assign across databases") - except ValueError: - pass - - # BUT! if you assign a FK object when the base object hasn't - # been saved yet, you implicitly assign the database for the - # base object. - chris = Person(name="Chris Mills") - html5 = Book(title="Dive into HTML5", published=datetime.date(2010, 3, 15)) - # initially, no db assigned - self.assertEquals(chris._state.db, None) - self.assertEquals(html5._state.db, None) - - # old object comes from 'other', so the new object is set to use 'other'... - dive.editor = chris - html5.editor = mark - # self.assertEquals(chris._state.db, 'other') - self.assertEquals(html5._state.db, 'other') - # ... but it isn't saved yet - self.assertEquals(list(Person.objects.using('other').values_list('name',flat=True)), - [u'Mark Pilgrim']) - self.assertEquals(list(Book.objects.using('other').values_list('title',flat=True)), - [u'Dive into Python']) - - # When saved (no using required), new objects goes to 'other' - chris.save() - html5.save() - self.assertEquals(list(Person.objects.using('default').values_list('name',flat=True)), - [u'Marty Alchin']) - self.assertEquals(list(Person.objects.using('other').values_list('name',flat=True)), - [u'Chris Mills', u'Mark Pilgrim']) - self.assertEquals(list(Book.objects.using('default').values_list('title',flat=True)), - [u'Pro Django']) - self.assertEquals(list(Book.objects.using('other').values_list('title',flat=True)), - [u'Dive into HTML5', u'Dive into Python']) - - # This also works if you assign the FK in the constructor - water = Book(title="Dive into Water", published=datetime.date(2001, 1, 1), editor=mark) - self.assertEquals(water._state.db, 'other') - # ... but it isn't saved yet - self.assertEquals(list(Book.objects.using('default').values_list('title',flat=True)), - [u'Pro Django']) - self.assertEquals(list(Book.objects.using('other').values_list('title',flat=True)), - [u'Dive into HTML5', u'Dive into Python']) - - # When saved, the new book goes to 'other' - water.save() - self.assertEquals(list(Book.objects.using('default').values_list('title',flat=True)), - [u'Pro Django']) - self.assertEquals(list(Book.objects.using('other').values_list('title',flat=True)), - [u'Dive into HTML5', u'Dive into Python', u'Dive into Water']) +# def test_foreign_key_cross_database_protection(self): +# "Operations that involve sharing FK objects across databases raise an error" +# # Create a book and author on the default database +# pro = Book.objects.create(title="Pro Django", +# published=datetime.date(2008, 12, 16)) + +# marty = Person.objects.create(name="Marty Alchin") + +# # Create a book and author on the other database +# dive = Book.objects.using('other').create(title="Dive into Python", +# published=datetime.date(2009, 5, 4)) + +# mark = Person.objects.using('other').create(name="Mark Pilgrim") + +# # Set a foreign key with an object from a different database +# try: +# dive.editor = marty +# self.fail("Shouldn't be able to assign across databases") +# except ValueError: +# pass + +# # Set a foreign key set with an object from a different database +# try: +# marty.edited = [pro, dive] +# self.fail("Shouldn't be able to assign across databases") +# except ValueError: +# pass + +# # Add to a foreign key set with an object from a different database +# try: +# marty.edited.add(dive) +# self.fail("Shouldn't be able to assign across databases") +# except ValueError: +# pass + +# # BUT! if you assign a FK object when the base object hasn't +# # been saved yet, you implicitly assign the database for the +# # base object. +# chris = Person(name="Chris Mills") +# html5 = Book(title="Dive into HTML5", published=datetime.date(2010, 3, 15)) +# # initially, no db assigned +# self.assertEquals(chris._state.db, None) +# self.assertEquals(html5._state.db, None) + +# # old object comes from 'other', so the new object is set to use 'other'... +# dive.editor = chris +# html5.editor = mark +# # self.assertEquals(chris._state.db, 'other') +# self.assertEquals(html5._state.db, 'other') +# # ... but it isn't saved yet +# self.assertEquals(list(Person.objects.using('other').values_list('name',flat=True)), +# [u'Mark Pilgrim']) +# self.assertEquals(list(Book.objects.using('other').values_list('title',flat=True)), +# [u'Dive into Python']) + +# # When saved (no using required), new objects goes to 'other' +# chris.save() +# html5.save() +# self.assertEquals(list(Person.objects.using('default').values_list('name',flat=True)), +# [u'Marty Alchin']) +# self.assertEquals(list(Person.objects.using('other').values_list('name',flat=True)), +# [u'Chris Mills', u'Mark Pilgrim']) +# self.assertEquals(list(Book.objects.using('default').values_list('title',flat=True)), +# [u'Pro Django']) +# self.assertEquals(list(Book.objects.using('other').values_list('title',flat=True)), +# [u'Dive into HTML5', u'Dive into Python']) + +# # This also works if you assign the FK in the constructor +# water = Book(title="Dive into Water", published=datetime.date(2001, 1, 1), editor=mark) +# self.assertEquals(water._state.db, 'other') +# # ... but it isn't saved yet +# self.assertEquals(list(Book.objects.using('default').values_list('title',flat=True)), +# [u'Pro Django']) +# self.assertEquals(list(Book.objects.using('other').values_list('title',flat=True)), +# [u'Dive into HTML5', u'Dive into Python']) + +# # When saved, the new book goes to 'other' +# water.save() +# self.assertEquals(list(Book.objects.using('default').values_list('title',flat=True)), +# [u'Pro Django']) +# self.assertEquals(list(Book.objects.using('other').values_list('title',flat=True)), +# [u'Dive into HTML5', u'Dive into Python', u'Dive into Water']) def test_generic_key_separation(self): "Generic fields are constrained to a single database" @@ -555,56 +555,56 @@ def test_generic_key_reverse_operations(self): self.assertEquals(list(Review.objects.using('other').filter(object_id=dive.pk).values_list('source', flat=True)), [u'Python Daily']) - def test_generic_key_cross_database_protection(self): - "Operations that involve sharing FK objects across databases raise an error" - # Create a book and author on the default database - pro = Book.objects.create(title="Pro Django", - published=datetime.date(2008, 12, 16)) - - review1 = Review.objects.create(source="Python Monthly", content_object=pro) - - # Create a book and author on the other database - dive = Book.objects.using('other').create(title="Dive into Python", - published=datetime.date(2009, 5, 4)) - - review2 = Review.objects.using('other').create(source="Python Weekly", content_object=dive) - - # Set a foreign key with an object from a different database - try: - review1.content_object = dive - self.fail("Shouldn't be able to assign across databases") - except ValueError: - pass - - # Add to a foreign key set with an object from a different database - try: - dive.reviews.add(review1) - self.fail("Shouldn't be able to assign across databases") - except ValueError: - pass - - # BUT! if you assign a FK object when the base object hasn't - # been saved yet, you implicitly assign the database for the - # base object. - review3 = Review(source="Python Daily") - # initially, no db assigned - self.assertEquals(review3._state.db, None) - - # Dive comes from 'other', so review3 is set to use 'other'... - review3.content_object = dive - self.assertEquals(review3._state.db, 'other') - # ... but it isn't saved yet - self.assertEquals(list(Review.objects.using('default').filter(object_id=pro.pk).values_list('source', flat=True)), - [u'Python Monthly']) - self.assertEquals(list(Review.objects.using('other').filter(object_id=dive.pk).values_list('source',flat=True)), - [u'Python Weekly']) - - # When saved, John goes to 'other' - review3.save() - self.assertEquals(list(Review.objects.using('default').filter(object_id=pro.pk).values_list('source', flat=True)), - [u'Python Monthly']) - self.assertEquals(list(Review.objects.using('other').filter(object_id=dive.pk).values_list('source',flat=True)), - [u'Python Daily', u'Python Weekly']) +# def test_generic_key_cross_database_protection(self): +## "Operations that involve sharing FK objects across databases raise an error" +## # Create a book and author on the default database +## pro = Book.objects.create(title="Pro Django", +## published=datetime.date(2008, 12, 16)) + +## review1 = Review.objects.create(source="Python Monthly", content_object=pro) + +## # Create a book and author on the other database +## dive = Book.objects.using('other').create(title="Dive into Python", +## published=datetime.date(2009, 5, 4)) + +## review2 = Review.objects.using('other').create(source="Python Weekly", content_object=dive) + +## # Set a foreign key with an object from a different database +## try: +## review1.content_object = dive +## self.fail("Shouldn't be able to assign across databases") +## except ValueError: +## pass + +# # Add to a foreign key set with an object from a different database +# try: +# dive.reviews.add(review1) +# self.fail("Shouldn't be able to assign across databases") +# except ValueError: +# pass + +# # BUT! if you assign a FK object when the base object hasn't +# # been saved yet, you implicitly assign the database for the +# # base object. +# review3 = Review(source="Python Daily") +# # initially, no db assigned +# self.assertEquals(review3._state.db, None) + +# # Dive comes from 'other', so review3 is set to use 'other'... +# review3.content_object = dive +# self.assertEquals(review3._state.db, 'other') +# # ... but it isn't saved yet +# self.assertEquals(list(Review.objects.using('default').filter(object_id=pro.pk).values_list('source', flat=True)), +# [u'Python Monthly']) +# self.assertEquals(list(Review.objects.using('other').filter(object_id=dive.pk).values_list('source',flat=True)), +# [u'Python Weekly']) + +# # When saved, John goes to 'other' +# review3.save() +# self.assertEquals(list(Review.objects.using('default').filter(object_id=pro.pk).values_list('source', flat=True)), +# [u'Python Monthly']) +# self.assertEquals(list(Review.objects.using('other').filter(object_id=dive.pk).values_list('source',flat=True)), +# [u'Python Daily', u'Python Weekly']) def test_ordering(self): "get_next_by_XXX commands stick to a single database"