magic-removal: Moved related name clash check logic out of Options, and into the

validation phase of model loading.


git-svn-id: http://code.djangoproject.com/svn/django/branches/magic-removal@2155 bcc190cf-cafb-0310-a4f2-bffc1f526a37
This commit is contained in:
Russell Keith-Magee 2006-01-29 01:38:48 +00:00
parent d580b42d45
commit 5bac096399
3 changed files with 34 additions and 38 deletions

View File

@ -1,7 +1,7 @@
# Django management-related functions, including "CREATE TABLE" generation and
# development-server initialization.
import django
import django
from django.core.exceptions import ImproperlyConfigured
import os, re, sys, textwrap
from optparse import OptionParser
@ -766,6 +766,8 @@ class ModelErrorCollection:
def get_validation_errors(outfile):
"Validates all installed models. Writes errors, if any, to outfile. Returns number of errors."
from django.db import models
from django.db.models.fields.related import RelatedObject
e = ModelErrorCollection(outfile)
for cls in models.get_models():
opts = cls._meta
@ -802,6 +804,20 @@ def get_validation_errors(outfile):
if f.db_index not in (None, True, False):
e.add(opts, '"%s" field: "db_index" should be either None, True or False.' % f.name)
# Check to see if the related field will clash with any
# existing fields, m2m fields, m2m related objects or related objects
if f.rel:
rel_opts = f.rel.to._meta
rel_name = RelatedObject(f.rel.to, cls, f).OLD_get_accessor_name()
if rel_name in [r.name for r in rel_opts.fields]:
e.add(opts, "'%s.%s' related field: Clashes with field on '%s.%s'" % (opts.object_name, f.name, rel_opts.object_name, rel_name))
elif rel_name in [r.name for r in rel_opts.many_to_many]:
e.add(opts, "'%s.%s' related field: Clashes with m2m field on '%s.%s'" % (opts.object_name, f.name, rel_opts.object_name, rel_name))
elif rel_name in [r.OLD_get_accessor_name() for r in rel_opts.get_all_related_many_to_many_objects()]:
e.add(opts, "'%s.%s' related field: Clashes with related m2m field '%s.%s'" % (opts.object_name, f.name, rel_opts.object_name, rel_name))
elif rel_name in [r.OLD_get_accessor_name() for r in rel_opts.get_all_related_objects() if r.field is not f]:
e.add(opts, "'%s.%s' related field: Clashes with related field on '%s.%s'" % (opts.object_name, f.name, rel_opts.object_name, rel_name))
# Check for multiple ManyToManyFields to the same object, and
# verify "singular" is set in that case.
for i, f in enumerate(opts.many_to_many):
@ -809,6 +825,20 @@ def get_validation_errors(outfile):
if f.rel.to._meta == previous_f.rel.to._meta and f.rel.singular == previous_f.rel.singular:
e.add(opts, 'The "%s" field requires a "singular" parameter, because the %s model has more than one ManyToManyField to the same model (%s).' % (f.name, opts.object_name, previous_f.rel.to._meta.object_name))
# Check to see if the related m2m field will clash with any
# existing fields, m2m fields, m2m related objects or related objects
if f.rel:
rel_opts = f.rel.to._meta
rel_name = RelatedObject(f.rel.to, cls, f).OLD_get_accessor_name()
if rel_name in [r.name for r in rel_opts.fields]:
e.add(opts, "'%s.%s' related m2m field: Clashes with field on '%s.%s'" % (opts.object_name, f.name, rel_opts.object_name, rel_name))
elif rel_name in [r.name for r in rel_opts.many_to_many]:
e.add(opts, "'%s.%s' related m2m field: Clashes with m2m field on '%s.%s'" % (opts.object_name, f.name, rel_opts.object_name, rel_name))
elif rel_name in [r.OLD_get_accessor_name() for r in rel_opts.get_all_related_many_to_many_objects() if r.field is not f]:
e.add(opts, "'%s.%s' related m2m field: Clashes with related m2m field '%s.%s'" % (opts.object_name, f.name, rel_opts.object_name, rel_name))
elif rel_name in [r.OLD_get_accessor_name() for r in rel_opts.get_all_related_objects()]:
e.add(opts, "'%s.%s' related m2m field: Clashes with related field on '%s.%s'" % (opts.object_name, f.name, rel_opts.object_name, rel_name))
# Check admin attribute.
if opts.admin is not None:
if not isinstance(opts.admin, models.AdminOptions):

View File

@ -27,8 +27,6 @@ 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."

View File

@ -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, FieldCollision
from django.db.models.fields import AutoField, FieldDoesNotExist
from django.db.models.loading import get_models
from django.db.models.query import orderlist2sql
from bisect import bisect
@ -123,23 +123,7 @@ class Options:
for klass in get_models():
for f in klass._meta.fields:
if f.rel and self == f.rel.to._meta:
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)
rel_objs.append(RelatedObject(f.rel.to, klass, f))
self._all_related_objects = rel_objs
return rel_objs
@ -173,23 +157,7 @@ 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_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)
rel_objs.append(RelatedObject(f.rel.to, klass, f))
self._all_related_many_to_many_objects = rel_objs
return rel_objs