From feee6d8805b8f6f955406ddec834ff577826065f Mon Sep 17 00:00:00 2001 From: Russell Keith-Magee Date: Sat, 28 Jan 2006 17:58:44 +0000 Subject: [PATCH] magic-removal: Added checks to prevent creation of models with related/m2m field names that collide with defined field names git-svn-id: http://code.djangoproject.com/svn/django/branches/magic-removal@2146 bcc190cf-cafb-0310-a4f2-bffc1f526a37 --- django/db/models/fields/__init__.py | 2 ++ django/db/models/options.py | 38 ++++++++++++++++++++++++++--- 2 files changed, 37 insertions(+), 3 deletions(-) diff --git a/django/db/models/fields/__init__.py b/django/db/models/fields/__init__.py index b0883f1e73..19279d45e7 100644 --- a/django/db/models/fields/__init__.py +++ b/django/db/models/fields/__init__.py @@ -27,6 +27,8 @@ get_ul_class = lambda x: 'radiolist%s' % ((x == HORIZONTAL) and ' inline' or '') class FieldDoesNotExist(Exception): pass +class FieldCollision(Exception): + pass def manipulator_validator_unique(f, opts, self, field_data, all_data): "Validates that the value is unique for this field." diff --git a/django/db/models/options.py b/django/db/models/options.py index 026104aa0e..652d9446bb 100644 --- a/django/db/models/options.py +++ b/django/db/models/options.py @@ -1,6 +1,6 @@ from django.db.models.related import RelatedObject from django.db.models.fields.related import ManyToMany -from django.db.models.fields import AutoField, FieldDoesNotExist +from django.db.models.fields import AutoField, FieldDoesNotExist, FieldCollision from django.db.models.loading import get_models from django.db.models.query import orderlist2sql from bisect import bisect @@ -123,7 +123,23 @@ class Options: for klass in get_models(): for f in klass._meta.fields: if f.rel and self == f.rel.to._meta: - rel_objs.append(RelatedObject(f.rel.to, klass, f)) + rel_obj = RelatedObject(f.rel.to, klass, f) + # Check to see if the new related field will clash with any + # existing fields, m2m fields, m2m related objects or related objects + if rel_obj.OLD_get_accessor_name() in [r.name for r in f.rel.to._meta.fields]: + raise FieldCollision, 'Related field ' + klass._meta.object_name + \ + '.' + f.name + ' clashes with existing field on ' + self.object_name + elif rel_obj.OLD_get_accessor_name() in [r.name for r in f.rel.to._meta.many_to_many]: + raise FieldCollision, 'Related field ' + klass._meta.object_name + \ + '.' + f.name + ' clashes with existing m2m field on ' + self.object_name + elif rel_obj.OLD_get_accessor_name() in [r.name for r in f.rel.to._meta.get_all_related_many_to_many_objects()]: + raise FieldCollision, 'Related field ' + klass._meta.object_name + \ + '.' + f.name + ' clashes with existing related m2m field on ' + self.object_name + elif rel_obj.OLD_get_accessor_name() in [r.OLD_get_accessor_name() for r in rel_objs]: + raise FieldCollision, 'Related field ' + klass._meta.object_name + \ + '.' + f.name + ' clashes with existing related field on ' + self.object_name + else: + rel_objs.append(rel_obj) self._all_related_objects = rel_objs return rel_objs @@ -157,7 +173,23 @@ class Options: for klass in get_models(): for f in klass._meta.many_to_many: if f.rel and self == f.rel.to._meta: - rel_objs.append(RelatedObject(f.rel.to, klass, f)) + rel_obj = RelatedObject(f.rel.to, klass, f) + # Check to see if the new related field will clash with any + # existing fields, m2m fields, m2m related objects or related objects + if rel_obj.OLD_get_accessor_name() in [r.name for r in f.rel.to._meta.fields]: + raise FieldCollision, 'Related field ' + klass._meta.object_name + \ + '.' + f.name + ' clashes with existing field on ' + self.object_name + elif rel_obj.OLD_get_accessor_name() in [r.name for r in f.rel.to._meta.many_to_many]: + raise FieldCollision, 'Related field ' + klass._meta.object_name + \ + '.' + f.name + ' clashes with existing m2m field on ' + self.object_name + elif rel_obj.OLD_get_accessor_name() in [r.OLD_get_accessor_name() for r in f.rel.to._meta.get_all_related_objects()]: + raise FieldCollision, 'Related field ' + klass._meta.object_name + \ + '.' + f.name + ' clashes with existing related field on ' + self.object_name + elif rel_obj.OLD_get_accessor_name() in [r.name for r in rel_objs]: + raise FieldCollision, 'Related field ' + klass._meta.object_name + \ + '.' + f.name + ' clashes with existing related m2m field on ' + self.object_name + else: + rel_objs.append(rel_obj) self._all_related_many_to_many_objects = rel_objs return rel_objs