Skip to content

Commit

Permalink
[soc2009/multidb] Fixed a problem with m2m descriptors not sticking t…
Browse files Browse the repository at this point in the history
…o the right database. Patch from Russell Keith-Magee.

git-svn-id: http://code.djangoproject.com/svn/django/branches/soc2009/multidb@11873 bcc190cf-cafb-0310-a4f2-bffc1f526a37
  • Loading branch information
alex committed Dec 16, 2009
1 parent 05b4d2f commit fc36471
Show file tree
Hide file tree
Showing 3 changed files with 32 additions and 5 deletions.
3 changes: 3 additions & 0 deletions TODO
Original file line number Diff line number Diff line change
Expand Up @@ -5,6 +5,9 @@ Required for v1.2
~~~~~~~~~~~~~~~~~

* Modify the admin interface to support multiple databases (doh).
- Document how it is done
- Modify m2m widgets to stick to the same database as parent
- Modify inlines to stick to same database as parent

Optional for v1.2
~~~~~~~~~~~~~~~~~
Expand Down
13 changes: 8 additions & 5 deletions django/db/models/fields/related.py
Original file line number Diff line number Diff line change
Expand Up @@ -439,7 +439,7 @@ def __init__(self, model=None, core_filters=None, instance=None, symmetrical=Non
raise ValueError("%r instance needs to have a primary key value before a many-to-many relationship can be used." % instance.__class__.__name__)

def get_query_set(self):
return superclass.get_query_set(self)._next_is_sticky().filter(**(self.core_filters))
return superclass.get_query_set(self).using(self.instance._state.db)._next_is_sticky().filter(**(self.core_filters))

# If the ManyToMany relation has an intermediary model,
# the add and remove methods do not exist.
Expand Down Expand Up @@ -709,7 +709,7 @@ def get_related_field(self):

class ForeignKey(RelatedField, Field):
"""Foreign Key (type determined by related field)"""

empty_strings_allowed = False
def __init__(self, to, to_field=None, rel_class=ManyToOneRel, **kwargs):
try:
Expand Down Expand Up @@ -809,7 +809,7 @@ def db_type(self, connection):

class OneToOneField(ForeignKey):
"""One-to-one relationship
A OneToOneField is essentially the same as a ForeignKey, with the exception
that always carries a "unique" constraint with it and the reverse relation
always returns the object pointed to (since there will only ever be one),
Expand Down Expand Up @@ -869,7 +869,7 @@ def set_managed(field, model, cls):

class ManyToManyField(RelatedField, Field):
"""Many-to-many relationship"""

def __init__(self, to, **kwargs):
try:
assert not to._meta.abstract, "%s cannot define a relation with abstract class %s" % (self.__class__.__name__, to._meta.object_name)
Expand Down Expand Up @@ -1032,7 +1032,10 @@ def save_form_data(self, instance, data):
setattr(instance, self.attname, data)

def formfield(self, **kwargs):
defaults = {'form_class': forms.ModelMultipleChoiceField, 'queryset': self.rel.to._default_manager.complex_filter(self.rel.limit_choices_to)}
defaults = {
'form_class': forms.ModelMultipleChoiceField,
'queryset': self.rel.to._default_manager.complex_filter(self.rel.limit_choices_to)
}
defaults.update(kwargs)
# If initial is passed in, it's a list of related objects, but the
# MultipleChoiceField takes a list of IDs.
Expand Down
21 changes: 21 additions & 0 deletions tests/regressiontests/multiple_database/tests.py
Original file line number Diff line number Diff line change
Expand Up @@ -160,6 +160,17 @@ def test_m2m_separation(self):
self.assertEquals(list(Book.objects.using('other').filter(authors__name='Mark Pilgrim').values_list('title', flat=True)),
[u'Dive into Python'])

# Reget the objects to clear caches
dive = Book.objects.using('other').get(title="Dive into Python")
mark = Author.objects.using('other').get(name="Mark Pilgrim")

# Retrive related object by descriptor. Related objects should be database-baound
self.assertEquals(list(dive.authors.all().values_list('name', flat=True)),
[u'Mark Pilgrim'])

self.assertEquals(list(mark.book_set.all().values_list('title', flat=True)),
[u'Dive into Python'])

def test_m2m_forward_operations(self):
"M2M forward manipulations are all constrained to a single DB"
# Create a book and author on the other database
Expand Down Expand Up @@ -286,6 +297,16 @@ def test_foreign_key_separation(self):
self.assertEquals(list(Book.objects.using('other').filter(favourite_of__name='Mark Pilgrim').values_list('title', flat=True)),
[u'Dive into Python'])

# Reget the objects to clear caches
dive = Book.objects.using('other').get(title="Dive into Python")
mark = Author.objects.using('other').get(name="Mark Pilgrim")

# Retrive related object by descriptor. Related objects should be database-baound
self.assertEquals(list(dive.favourite_of.all().values_list('name', flat=True)),
[u'Mark Pilgrim'])

self.assertEquals(mark.favourite_book.title, u'Dive into Python')

def test_foreign_key_reverse_operations(self):
"FK reverse manipulations are all constrained to a single DB"
dive = Book.objects.using('other').create(title="Dive into Python",
Expand Down

0 comments on commit fc36471

Please sign in to comment.