Skip to content

Commit

Permalink
magic-removal: Refs #1346 -- Refactored query logic for m2m descripto…
Browse files Browse the repository at this point in the history
…r fields, and added logic to m2m name methods to allow m2m_recursive tests to create a valid SQL table.

git-svn-id: http://code.djangoproject.com/svn/django/branches/magic-removal@2381 bcc190cf-cafb-0310-a4f2-bffc1f526a37
  • Loading branch information
freakboy3742 committed Feb 24, 2006
1 parent 64cb7da commit 492d214
Show file tree
Hide file tree
Showing 3 changed files with 29 additions and 12 deletions.
33 changes: 28 additions & 5 deletions django/db/models/fields/related.py
Original file line number Diff line number Diff line change
Expand Up @@ -46,6 +46,10 @@ def manipulator_valid_rel_key(f, self, field_data, all_data):
class RelatedField(object):
def contribute_to_class(self, cls, name):
sup = super(RelatedField, self)

# Add an accessor to allow easy determination of the related query path for this field
self.related_query_name = curry(self._get_related_query_name, cls._meta)

if hasattr(sup, 'contribute_to_class'):
sup.contribute_to_class(cls, name)
other = self.rel.to
Expand All @@ -66,6 +70,12 @@ def do_related_class(self, other, cls):
related = RelatedObject(other, cls, self)
self.contribute_to_related_class(other, related)

def _get_related_query_name(self, opts):
# This method defines the name that can be used to identify this related object
# in a table-spanning query. It uses the lower-cased object_name by default,
# but this can be overridden with the "related_name" option.
return self.rel.related_name or opts.object_name.lower()

class SingleRelatedObjectDescriptor(object):
# This class provides the functionality that makes the related-object
# managers available as attributes on a model class, for fields that have
Expand Down Expand Up @@ -241,9 +251,9 @@ def clear(self):
manager = RelatedManager()

if self.rel_type == 'o2m':
manager.core_filters = {'%s__%s__exact' % (rel_field.name, rel_field.rel.to._meta.pk.name): getattr(instance, rel_field.rel.get_related_field().attname)}
manager.core_filters = {'%s__pk' % rel_field.name: getattr(instance, rel_field.rel.get_related_field().attname)}
else:
manager.core_filters = {'%s__%s__exact' % (rel_field.name, instance_type._meta.pk.name): instance._get_pk_val()}
manager.core_filters = {'%s__pk' % rel_field.name: instance._get_pk_val()}

manager.model = self.related.model

Expand Down Expand Up @@ -285,6 +295,8 @@ def get_query_set(self):
],
params = [instance._get_pk_val()]
)
return superclass.get_query_set(self).filter(**(self.core_filters))

def add(self, *objs, **kwargs):
_add_m2m_items(self, superclass, rel_model, join_table, source_col_name,
target_col_name, instance._get_pk_val(), *objs, **kwargs)
Expand All @@ -300,6 +312,9 @@ def clear(self):
clear.alters_data = True

manager = RelatedManager()

manager.core_filters = {'%s__pk' % self.field.related_query_name() : instance._get_pk_val()}

manager.model = rel_model

return manager
Expand Down Expand Up @@ -470,11 +485,19 @@ def _get_m2m_db_table(self, opts):

def _get_m2m_column_name(self, related):
"Function that can be curried to provide the source column name for the m2m table"
return related.model._meta.object_name.lower() + '_id'

# If this is an m2m relation to self, avoid the inevitable name clash
if related.model == related.parent_model:
return 'from_' + related.model._meta.object_name.lower() + '_id'
else:
return related.model._meta.object_name.lower() + '_id'

def _get_m2m_reverse_name(self, related):
"Function that can be curried to provide the related column name for the m2m table"
return related.parent_model._meta.object_name.lower() + '_id'
# If this is an m2m relation to self, avoid the inevitable name clash
if related.model == related.parent_model:
return 'to_' + related.parent_model._meta.object_name.lower() + '_id'
else:
return related.parent_model._meta.object_name.lower() + '_id'

def isValidIDList(self, field_data, all_data):
"Validates that the value is a valid list of foreign keys"
Expand Down
2 changes: 1 addition & 1 deletion django/db/models/query.py
Original file line number Diff line number Diff line change
Expand Up @@ -613,7 +613,7 @@ def find_field(name, field_list, related_query):
Returns None if there are no matches, or several matches.
"""
if related_query:
matches = [f for f in field_list if f.get_query_name() == name]
matches = [f for f in field_list if f.field.related_query_name() == name]
else:
matches = [f for f in field_list if f.name == name]
if len(matches) != 1:
Expand Down
6 changes: 0 additions & 6 deletions django/db/models/related.py
Original file line number Diff line number Diff line change
Expand Up @@ -74,9 +74,3 @@ def get_accessor_name(self):
# many-to-many objects. It uses the lower-cased object_name + "_set",
# but this can be overridden with the "related_name" option.
return self.field.rel.related_name or (self.opts.object_name.lower() + '_set')

def get_query_name(self):
# This method defines the name that can be used to identify this related object
# in a table-spanning query. It uses the lower-cased object_name by default,
# but this can be overridden with the "related_name" option.
return self.field.rel.related_name or self.opts.object_name.lower()

0 comments on commit 492d214

Please sign in to comment.