Skip to content

Commit

Permalink
Fixed #556 -- ManyToManyField join tables no longer assume the primar…
Browse files Browse the repository at this point in the history
…y keys of both associated tables are integers. Also added unit tests to confirm.

git-svn-id: http://code.djangoproject.com/svn/django/trunk@682 bcc190cf-cafb-0310-a4f2-bffc1f526a37
  • Loading branch information
adrianholovaty committed Sep 25, 2005
1 parent 2e8e256 commit c05cce5
Show file tree
Hide file tree
Showing 3 changed files with 27 additions and 11 deletions.
18 changes: 8 additions & 10 deletions django/core/management.py
Expand Up @@ -44,6 +44,11 @@ def _get_contenttype_insert(opts):
def _is_valid_dir_name(s):
return bool(re.search(r'^\w+$', s))

# If the foreign key points to an AutoField, the foreign key should be an
# IntegerField, not an AutoField. Otherwise, the foreign key should be the same
# type of field as the field to which it points.
get_rel_data_type = lambda f: (f.__class__.__name__ == 'AutoField') and 'IntegerField' or f.__class__.__name__

def get_sql_create(mod):
"Returns a list of the CREATE TABLE SQL statements for the given module."
from django.core import db, meta
Expand All @@ -54,14 +59,7 @@ def get_sql_create(mod):
for f in opts.fields:
if isinstance(f, meta.ForeignKey):
rel_field = f.rel.get_related_field()
# If the foreign key points to an AutoField, the foreign key
# should be an IntegerField, not an AutoField. Otherwise, the
# foreign key should be the same type of field as the field
# to which it points.
if rel_field.__class__.__name__ == 'AutoField':
data_type = 'IntegerField'
else:
data_type = rel_field.__class__.__name__
data_type = get_rel_data_type(rel_field)
else:
rel_field = f
data_type = f.__class__.__name__
Expand Down Expand Up @@ -94,9 +92,9 @@ def get_sql_create(mod):
table_output = ['CREATE TABLE %s (' % f.get_m2m_db_table(opts)]
table_output.append(' id %s NOT NULL PRIMARY KEY,' % db.DATA_TYPES['AutoField'])
table_output.append(' %s_id %s NOT NULL REFERENCES %s (%s),' % \
(opts.object_name.lower(), db.DATA_TYPES['IntegerField'], opts.db_table, opts.pk.column))
(opts.object_name.lower(), db.DATA_TYPES[get_rel_data_type(opts.pk)] % opts.pk.__dict__, opts.db_table, opts.pk.column))
table_output.append(' %s_id %s NOT NULL REFERENCES %s (%s),' % \
(f.rel.to.object_name.lower(), db.DATA_TYPES['IntegerField'], f.rel.to.db_table, f.rel.to.pk.column))
(f.rel.to.object_name.lower(), db.DATA_TYPES[get_rel_data_type(f.rel.to.pk)] % f.rel.to.pk.__dict__, f.rel.to.db_table, f.rel.to.pk.column))
table_output.append(' UNIQUE (%s_id, %s_id)' % (opts.object_name.lower(), f.rel.to.object_name.lower()))
table_output.append(');')
final_output.append('\n'.join(table_output))
Expand Down
1 change: 0 additions & 1 deletion django/core/meta/__init__.py
Expand Up @@ -893,7 +893,6 @@ def method_get_many_to_many(field_with_rel, self):
# Handles setting many-to-many relationships.
# Example: Poll.set_sites()
def method_set_many_to_many(rel_field, self, id_list):
id_list = map(int, id_list) # normalize to integers
current_ids = [obj.id for obj in method_get_many_to_many(rel_field, self)]
ids_to_add, ids_to_delete = dict([(i, 1) for i in id_list]), []
for current_id in current_ids:
Expand Down
19 changes: 19 additions & 0 deletions tests/testapp/models/custom_pk.py
Expand Up @@ -17,6 +17,16 @@ class META:
def __repr__(self):
return "%s %s" % (self.first_name, self.last_name)

class Business(meta.Model):
name = meta.CharField(maxlength=20, primary_key=True)
employees = meta.ManyToManyField(Employee)
class META:
verbose_name_plural = 'businesses'
module_name = 'businesses'

def __repr__(self):
return self.name

API_TESTS = """
>>> dan = employees.Employee(employee_code='ABC123', first_name='Dan', last_name='Jones')
>>> dan.save()
Expand All @@ -43,4 +53,13 @@ def __repr__(self):
>>> fran.save()
>>> employees.get_list(last_name__exact='Jones')
[Dan Jones, Fran Jones]
>>> b = businesses.Business(name='Sears')
>>> b.save()
>>> b.set_employees([dan.employee_code, fran.employee_code])
True
>>> b.get_employee_list()
[Dan Jones, Fran Jones]
>>> fran.get_business_list()
[Sears]
"""

0 comments on commit c05cce5

Please sign in to comment.