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:
parent
d580b42d45
commit
5bac096399
|
@ -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):
|
||||
|
|
|
@ -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."
|
||||
|
|
|
@ -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
|
||||
|
||||
|
|
Loading…
Reference in New Issue