Fixed #556 -- ManyToManyField join tables no longer assume the primary 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
This commit is contained in:
parent
2e8e256fe8
commit
c05cce5c52
|
@ -44,6 +44,11 @@ def _get_contenttype_insert(opts):
|
||||||
def _is_valid_dir_name(s):
|
def _is_valid_dir_name(s):
|
||||||
return bool(re.search(r'^\w+$', 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):
|
def get_sql_create(mod):
|
||||||
"Returns a list of the CREATE TABLE SQL statements for the given module."
|
"Returns a list of the CREATE TABLE SQL statements for the given module."
|
||||||
from django.core import db, meta
|
from django.core import db, meta
|
||||||
|
@ -54,14 +59,7 @@ def get_sql_create(mod):
|
||||||
for f in opts.fields:
|
for f in opts.fields:
|
||||||
if isinstance(f, meta.ForeignKey):
|
if isinstance(f, meta.ForeignKey):
|
||||||
rel_field = f.rel.get_related_field()
|
rel_field = f.rel.get_related_field()
|
||||||
# If the foreign key points to an AutoField, the foreign key
|
data_type = get_rel_data_type(rel_field)
|
||||||
# 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__
|
|
||||||
else:
|
else:
|
||||||
rel_field = f
|
rel_field = f
|
||||||
data_type = f.__class__.__name__
|
data_type = f.__class__.__name__
|
||||||
|
@ -94,9 +92,9 @@ def get_sql_create(mod):
|
||||||
table_output = ['CREATE TABLE %s (' % f.get_m2m_db_table(opts)]
|
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(' id %s NOT NULL PRIMARY KEY,' % db.DATA_TYPES['AutoField'])
|
||||||
table_output.append(' %s_id %s NOT NULL REFERENCES %s (%s),' % \
|
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),' % \
|
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(' UNIQUE (%s_id, %s_id)' % (opts.object_name.lower(), f.rel.to.object_name.lower()))
|
||||||
table_output.append(');')
|
table_output.append(');')
|
||||||
final_output.append('\n'.join(table_output))
|
final_output.append('\n'.join(table_output))
|
||||||
|
|
|
@ -893,7 +893,6 @@ def method_get_many_to_many(field_with_rel, self):
|
||||||
# Handles setting many-to-many relationships.
|
# Handles setting many-to-many relationships.
|
||||||
# Example: Poll.set_sites()
|
# Example: Poll.set_sites()
|
||||||
def method_set_many_to_many(rel_field, self, id_list):
|
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)]
|
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]), []
|
ids_to_add, ids_to_delete = dict([(i, 1) for i in id_list]), []
|
||||||
for current_id in current_ids:
|
for current_id in current_ids:
|
||||||
|
|
|
@ -17,6 +17,16 @@ class Employee(meta.Model):
|
||||||
def __repr__(self):
|
def __repr__(self):
|
||||||
return "%s %s" % (self.first_name, self.last_name)
|
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 = """
|
API_TESTS = """
|
||||||
>>> dan = employees.Employee(employee_code='ABC123', first_name='Dan', last_name='Jones')
|
>>> dan = employees.Employee(employee_code='ABC123', first_name='Dan', last_name='Jones')
|
||||||
>>> dan.save()
|
>>> dan.save()
|
||||||
|
@ -43,4 +53,13 @@ EmployeeDoesNotExist: Employee does not exist for {'pk': 'foo'}
|
||||||
>>> fran.save()
|
>>> fran.save()
|
||||||
>>> employees.get_list(last_name__exact='Jones')
|
>>> employees.get_list(last_name__exact='Jones')
|
||||||
[Dan Jones, Fran 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]
|
||||||
"""
|
"""
|
||||||
|
|
Loading…
Reference in New Issue