Edited model and field checks for grammar and consistency.
This commit is contained in:
parent
bc4dc6e99c
commit
82ac389486
|
@ -36,14 +36,14 @@ def check_model_signals(app_configs=None, **kwargs):
|
||||||
description = "An instance of the `%s` class" % receiver.__class__.__name__
|
description = "An instance of the `%s` class" % receiver.__class__.__name__
|
||||||
errors.append(
|
errors.append(
|
||||||
Error(
|
Error(
|
||||||
"%s was connected to the `%s` signal "
|
"%s was connected to the '%s' signal "
|
||||||
"with a lazy reference to the '%s' sender, "
|
"with a lazy reference to the '%s' sender, "
|
||||||
"which has not been installed." % (
|
"which has not been installed." % (
|
||||||
description, name, '.'.join(reference)
|
description, name, '.'.join(reference)
|
||||||
),
|
),
|
||||||
obj=receiver.__module__,
|
obj=receiver.__module__,
|
||||||
hint=None,
|
hint=None,
|
||||||
id='E014'
|
id='signals.E001'
|
||||||
)
|
)
|
||||||
)
|
)
|
||||||
return errors
|
return errors
|
||||||
|
|
|
@ -197,10 +197,10 @@ class Field(RegisterLookupMixin):
|
||||||
if self.name.endswith('_'):
|
if self.name.endswith('_'):
|
||||||
return [
|
return [
|
||||||
checks.Error(
|
checks.Error(
|
||||||
'Field names must not end with underscores.',
|
'Field names must not end with an underscore.',
|
||||||
hint=None,
|
hint=None,
|
||||||
obj=self,
|
obj=self,
|
||||||
id='E001',
|
id='fields.E001',
|
||||||
)
|
)
|
||||||
]
|
]
|
||||||
elif '__' in self.name:
|
elif '__' in self.name:
|
||||||
|
@ -209,16 +209,16 @@ class Field(RegisterLookupMixin):
|
||||||
'Field names must not contain "__".',
|
'Field names must not contain "__".',
|
||||||
hint=None,
|
hint=None,
|
||||||
obj=self,
|
obj=self,
|
||||||
id='E052',
|
id='fields.E002',
|
||||||
)
|
)
|
||||||
]
|
]
|
||||||
elif self.name == 'pk':
|
elif self.name == 'pk':
|
||||||
return [
|
return [
|
||||||
checks.Error(
|
checks.Error(
|
||||||
'Cannot use "pk" as a field name since it is a reserved name.',
|
"'pk' is a reserved word that cannot be used as a field name.",
|
||||||
hint=None,
|
hint=None,
|
||||||
obj=self,
|
obj=self,
|
||||||
id='E051',
|
id='fields.E003',
|
||||||
)
|
)
|
||||||
]
|
]
|
||||||
else:
|
else:
|
||||||
|
@ -230,10 +230,10 @@ class Field(RegisterLookupMixin):
|
||||||
not is_iterable(self.choices)):
|
not is_iterable(self.choices)):
|
||||||
return [
|
return [
|
||||||
checks.Error(
|
checks.Error(
|
||||||
'"choices" must be an iterable (e.g., a list or tuple).',
|
"'choices' must be an iterable (e.g., a list or tuple).",
|
||||||
hint=None,
|
hint=None,
|
||||||
obj=self,
|
obj=self,
|
||||||
id='E033',
|
id='fields.E004',
|
||||||
)
|
)
|
||||||
]
|
]
|
||||||
elif any(isinstance(choice, six.string_types) or
|
elif any(isinstance(choice, six.string_types) or
|
||||||
|
@ -241,13 +241,11 @@ class Field(RegisterLookupMixin):
|
||||||
for choice in self.choices):
|
for choice in self.choices):
|
||||||
return [
|
return [
|
||||||
checks.Error(
|
checks.Error(
|
||||||
('All "choices" elements must be a tuple of two '
|
("'choices' must be an iterable containing "
|
||||||
'elements (the first one is the actual value '
|
"(actual value, human readable name) tuples."),
|
||||||
'to be stored and the second element is '
|
|
||||||
'the human-readable name).'),
|
|
||||||
hint=None,
|
hint=None,
|
||||||
obj=self,
|
obj=self,
|
||||||
id='E034',
|
id='fields.E005',
|
||||||
)
|
)
|
||||||
]
|
]
|
||||||
else:
|
else:
|
||||||
|
@ -259,10 +257,10 @@ class Field(RegisterLookupMixin):
|
||||||
if self.db_index not in (None, True, False):
|
if self.db_index not in (None, True, False):
|
||||||
return [
|
return [
|
||||||
checks.Error(
|
checks.Error(
|
||||||
'"db_index" must be either None, True or False.',
|
"'db_index' must be None, True or False.",
|
||||||
hint=None,
|
hint=None,
|
||||||
obj=self,
|
obj=self,
|
||||||
id='E035',
|
id='fields.E006',
|
||||||
)
|
)
|
||||||
]
|
]
|
||||||
else:
|
else:
|
||||||
|
@ -277,10 +275,10 @@ class Field(RegisterLookupMixin):
|
||||||
return [
|
return [
|
||||||
checks.Error(
|
checks.Error(
|
||||||
'Primary keys must not have null=True.',
|
'Primary keys must not have null=True.',
|
||||||
hint=('Set null=False on the field or '
|
hint=('Set null=False on the field, or '
|
||||||
'remove primary_key=True argument.'),
|
'remove primary_key=True argument.'),
|
||||||
obj=self,
|
obj=self,
|
||||||
id='E036',
|
id='fields.E007',
|
||||||
)
|
)
|
||||||
]
|
]
|
||||||
else:
|
else:
|
||||||
|
@ -864,10 +862,10 @@ class AutoField(Field):
|
||||||
if not self.primary_key:
|
if not self.primary_key:
|
||||||
return [
|
return [
|
||||||
checks.Error(
|
checks.Error(
|
||||||
'The field must have primary_key=True, because it is an AutoField.',
|
'AutoFields must set primary_key=True.',
|
||||||
hint=None,
|
hint=None,
|
||||||
obj=self,
|
obj=self,
|
||||||
id='E048',
|
id='fields.E100',
|
||||||
),
|
),
|
||||||
]
|
]
|
||||||
else:
|
else:
|
||||||
|
@ -940,10 +938,10 @@ class BooleanField(Field):
|
||||||
if getattr(self, 'null', False):
|
if getattr(self, 'null', False):
|
||||||
return [
|
return [
|
||||||
checks.Error(
|
checks.Error(
|
||||||
'BooleanFields do not acceps null values.',
|
'BooleanFields do not accept null values.',
|
||||||
hint='Use a NullBooleanField instead.',
|
hint='Use a NullBooleanField instead.',
|
||||||
obj=self,
|
obj=self,
|
||||||
id='E037',
|
id='fields.E110',
|
||||||
)
|
)
|
||||||
]
|
]
|
||||||
else:
|
else:
|
||||||
|
@ -1020,19 +1018,19 @@ class CharField(Field):
|
||||||
except TypeError:
|
except TypeError:
|
||||||
return [
|
return [
|
||||||
checks.Error(
|
checks.Error(
|
||||||
'The field must have "max_length" attribute.',
|
"CharFields must define a 'max_length' attribute.",
|
||||||
hint=None,
|
hint=None,
|
||||||
obj=self,
|
obj=self,
|
||||||
id='E038',
|
id='fields.E120',
|
||||||
)
|
)
|
||||||
]
|
]
|
||||||
except ValueError:
|
except ValueError:
|
||||||
return [
|
return [
|
||||||
checks.Error(
|
checks.Error(
|
||||||
'"max_length" must be a positive integer.',
|
"'max_length' must be a positive integer.",
|
||||||
hint=None,
|
hint=None,
|
||||||
obj=self,
|
obj=self,
|
||||||
id='E039',
|
id='fields.E121',
|
||||||
)
|
)
|
||||||
]
|
]
|
||||||
else:
|
else:
|
||||||
|
@ -1305,24 +1303,16 @@ class DecimalField(Field):
|
||||||
|
|
||||||
def check(self, **kwargs):
|
def check(self, **kwargs):
|
||||||
errors = super(DecimalField, self).check(**kwargs)
|
errors = super(DecimalField, self).check(**kwargs)
|
||||||
errors.extend(self._check_decimal_places_and_max_digits(**kwargs))
|
|
||||||
|
digits_errors = self._check_decimal_places()
|
||||||
|
digits_errors.extend(self._check_max_digits())
|
||||||
|
if not digits_errors:
|
||||||
|
errors.extend(self._check_decimal_places_and_max_digits(**kwargs))
|
||||||
|
else:
|
||||||
|
errors.extend(digits_errors)
|
||||||
return errors
|
return errors
|
||||||
|
|
||||||
def _check_decimal_places_and_max_digits(self, **kwargs):
|
def _check_decimal_places(self):
|
||||||
errors = self.__check_decimal_places()
|
|
||||||
errors += self.__check_max_digits()
|
|
||||||
if not errors and int(self.decimal_places) > int(self.max_digits):
|
|
||||||
errors.append(
|
|
||||||
checks.Error(
|
|
||||||
'"max_digits" must be greater or equal to "decimal_places".',
|
|
||||||
hint=None,
|
|
||||||
obj=self,
|
|
||||||
id='E040',
|
|
||||||
)
|
|
||||||
)
|
|
||||||
return errors
|
|
||||||
|
|
||||||
def __check_decimal_places(self):
|
|
||||||
try:
|
try:
|
||||||
decimal_places = int(self.decimal_places)
|
decimal_places = int(self.decimal_places)
|
||||||
if decimal_places < 0:
|
if decimal_places < 0:
|
||||||
|
@ -1330,25 +1320,25 @@ class DecimalField(Field):
|
||||||
except TypeError:
|
except TypeError:
|
||||||
return [
|
return [
|
||||||
checks.Error(
|
checks.Error(
|
||||||
'The field requires a "decimal_places" attribute.',
|
"DecimalFields must define a 'decimal_places' attribute.",
|
||||||
hint=None,
|
hint=None,
|
||||||
obj=self,
|
obj=self,
|
||||||
id='E041',
|
id='fields.E130',
|
||||||
)
|
)
|
||||||
]
|
]
|
||||||
except ValueError:
|
except ValueError:
|
||||||
return [
|
return [
|
||||||
checks.Error(
|
checks.Error(
|
||||||
'"decimal_places" attribute must be a non-negative integer.',
|
"'decimal_places' must be a non-negative integer.",
|
||||||
hint=None,
|
hint=None,
|
||||||
obj=self,
|
obj=self,
|
||||||
id='E042',
|
id='fields.E131',
|
||||||
)
|
)
|
||||||
]
|
]
|
||||||
else:
|
else:
|
||||||
return []
|
return []
|
||||||
|
|
||||||
def __check_max_digits(self):
|
def _check_max_digits(self):
|
||||||
try:
|
try:
|
||||||
max_digits = int(self.max_digits)
|
max_digits = int(self.max_digits)
|
||||||
if max_digits <= 0:
|
if max_digits <= 0:
|
||||||
|
@ -1356,24 +1346,36 @@ class DecimalField(Field):
|
||||||
except TypeError:
|
except TypeError:
|
||||||
return [
|
return [
|
||||||
checks.Error(
|
checks.Error(
|
||||||
'The field requires a "max_digits" attribute.',
|
"DecimalFields must define a 'max_digits' attribute.",
|
||||||
hint=None,
|
hint=None,
|
||||||
obj=self,
|
obj=self,
|
||||||
id='E043',
|
id='fields.E132',
|
||||||
)
|
)
|
||||||
]
|
]
|
||||||
except ValueError:
|
except ValueError:
|
||||||
return [
|
return [
|
||||||
checks.Error(
|
checks.Error(
|
||||||
'"max_digits" attribute must be a positive integer.',
|
"'max_digits' must be a positive integer.",
|
||||||
hint=None,
|
hint=None,
|
||||||
obj=self,
|
obj=self,
|
||||||
id='E044',
|
id='fields.E133',
|
||||||
)
|
)
|
||||||
]
|
]
|
||||||
else:
|
else:
|
||||||
return []
|
return []
|
||||||
|
|
||||||
|
def _check_decimal_places_and_max_digits(self, **kwargs):
|
||||||
|
if int(self.decimal_places) > int(self.max_digits):
|
||||||
|
return [
|
||||||
|
checks.Error(
|
||||||
|
"'max_digits' must be greater or equal to 'decimal_places'.",
|
||||||
|
hint=None,
|
||||||
|
obj=self,
|
||||||
|
id='fields.E134',
|
||||||
|
)
|
||||||
|
]
|
||||||
|
return []
|
||||||
|
|
||||||
def deconstruct(self):
|
def deconstruct(self):
|
||||||
name, path, args, kwargs = super(DecimalField, self).deconstruct()
|
name, path, args, kwargs = super(DecimalField, self).deconstruct()
|
||||||
if self.max_digits:
|
if self.max_digits:
|
||||||
|
@ -1481,10 +1483,10 @@ class FilePathField(Field):
|
||||||
if not self.allow_files and not self.allow_folders:
|
if not self.allow_files and not self.allow_folders:
|
||||||
return [
|
return [
|
||||||
checks.Error(
|
checks.Error(
|
||||||
'The field must have either "allow_files" or "allow_folders" set to True.',
|
"FilePathFields must have either 'allow_files' or 'allow_folders' set to True.",
|
||||||
hint=None,
|
hint=None,
|
||||||
obj=self,
|
obj=self,
|
||||||
id='E045',
|
id='fields.E140',
|
||||||
)
|
)
|
||||||
]
|
]
|
||||||
return []
|
return []
|
||||||
|
@ -1659,11 +1661,11 @@ class GenericIPAddressField(Field):
|
||||||
if not getattr(self, 'null', False) and getattr(self, 'blank', False):
|
if not getattr(self, 'null', False) and getattr(self, 'blank', False):
|
||||||
return [
|
return [
|
||||||
checks.Error(
|
checks.Error(
|
||||||
('The field cannot accept blank values if null values '
|
('GenericIPAddressFields cannot have blank=True if null=False, '
|
||||||
'are not allowed, as blank values are stored as null.'),
|
'as blank values are stored as nulls.'),
|
||||||
hint=None,
|
hint=None,
|
||||||
obj=self,
|
obj=self,
|
||||||
id='E046',
|
id='fields.E150',
|
||||||
)
|
)
|
||||||
]
|
]
|
||||||
return []
|
return []
|
||||||
|
|
|
@ -246,10 +246,10 @@ class FileField(Field):
|
||||||
if self._unique_set_explicitly:
|
if self._unique_set_explicitly:
|
||||||
return [
|
return [
|
||||||
checks.Error(
|
checks.Error(
|
||||||
'"unique" is not a valid argument for %s.' % self.__class__.__name__,
|
"'unique' is not a valid argument for a %s." % self.__class__.__name__,
|
||||||
hint=None,
|
hint=None,
|
||||||
obj=self,
|
obj=self,
|
||||||
id='E049',
|
id='fields.E200',
|
||||||
)
|
)
|
||||||
]
|
]
|
||||||
else:
|
else:
|
||||||
|
@ -259,10 +259,10 @@ class FileField(Field):
|
||||||
if self._primary_key_set_explicitly:
|
if self._primary_key_set_explicitly:
|
||||||
return [
|
return [
|
||||||
checks.Error(
|
checks.Error(
|
||||||
'"primary_key" is not a valid argument for %s.' % self.__class__.__name__,
|
"'primary_key' is not a valid argument for a %s." % self.__class__.__name__,
|
||||||
hint=None,
|
hint=None,
|
||||||
obj=self,
|
obj=self,
|
||||||
id='E050',
|
id='fields.E201',
|
||||||
)
|
)
|
||||||
]
|
]
|
||||||
else:
|
else:
|
||||||
|
@ -392,11 +392,11 @@ class ImageField(FileField):
|
||||||
except ImproperlyConfigured:
|
except ImproperlyConfigured:
|
||||||
return [
|
return [
|
||||||
checks.Error(
|
checks.Error(
|
||||||
'To use ImageFields, Pillow must be installed.',
|
'Cannot use ImageField because Pillow is not installed.',
|
||||||
hint=('Get Pillow at https://pypi.python.org/pypi/Pillow '
|
hint=('Get Pillow at https://pypi.python.org/pypi/Pillow '
|
||||||
'or run command "pip install pillow".'),
|
'or run command "pip install pillow".'),
|
||||||
obj=self,
|
obj=self,
|
||||||
id='E032',
|
id='fields.E210',
|
||||||
)
|
)
|
||||||
]
|
]
|
||||||
else:
|
else:
|
||||||
|
|
|
@ -108,13 +108,11 @@ class RelatedField(Field):
|
||||||
if rel_is_missing and (rel_is_string or not self.rel.to._meta.swapped):
|
if rel_is_missing and (rel_is_string or not self.rel.to._meta.swapped):
|
||||||
return [
|
return [
|
||||||
checks.Error(
|
checks.Error(
|
||||||
('The field has a relation with model %s, which '
|
("Field defines a relation with model '%s', which "
|
||||||
'has either not been installed or is abstract.') % model_name,
|
"is either not installed, or is abstract.") % model_name,
|
||||||
hint=('Ensure that you did not misspell the model name and '
|
hint=None,
|
||||||
'the model is not abstract. Does your INSTALLED_APPS '
|
|
||||||
'setting contain the app where %s is defined?') % model_name,
|
|
||||||
obj=self,
|
obj=self,
|
||||||
id='E030',
|
id='fields.E300',
|
||||||
)
|
)
|
||||||
]
|
]
|
||||||
return []
|
return []
|
||||||
|
@ -129,11 +127,11 @@ class RelatedField(Field):
|
||||||
)
|
)
|
||||||
return [
|
return [
|
||||||
checks.Error(
|
checks.Error(
|
||||||
('The field defines a relation with the model %s, '
|
("Field defines a relation with the model '%s', "
|
||||||
'which has been swapped out.') % model,
|
"which has been swapped out.") % model,
|
||||||
hint='Update the relation to point at settings.%s' % self.rel.to._meta.swappable,
|
hint="Update the relation to point at 'settings.%s'." % self.rel.to._meta.swappable,
|
||||||
obj=self,
|
obj=self,
|
||||||
id='E029',
|
id='fields.E301',
|
||||||
)
|
)
|
||||||
]
|
]
|
||||||
return []
|
return []
|
||||||
|
@ -190,22 +188,22 @@ class RelatedField(Field):
|
||||||
if clash_field.name == rel_name:
|
if clash_field.name == rel_name:
|
||||||
errors.append(
|
errors.append(
|
||||||
checks.Error(
|
checks.Error(
|
||||||
'Accessor for field %s clashes with field %s.' % (field_name, clash_name),
|
"Reverse accessor for '%s' clashes with field name '%s'." % (field_name, clash_name),
|
||||||
hint=('Rename field %s or add/change a related_name '
|
hint=("Rename field '%s', or add/change a related_name "
|
||||||
'argument to the definition for field %s.') % (clash_name, field_name),
|
"argument to the definition for field '%s'.") % (clash_name, field_name),
|
||||||
obj=self,
|
obj=self,
|
||||||
id='E014',
|
id='fields.E302',
|
||||||
)
|
)
|
||||||
)
|
)
|
||||||
|
|
||||||
if clash_field.name == rel_query_name:
|
if clash_field.name == rel_query_name:
|
||||||
errors.append(
|
errors.append(
|
||||||
checks.Error(
|
checks.Error(
|
||||||
'Reverse query name for field %s clashes with field %s.' % (field_name, clash_name),
|
"Reverse query name for '%s' clashes with field name '%s'." % (field_name, clash_name),
|
||||||
hint=('Rename field %s or add/change a related_name '
|
hint=("Rename field '%s', or add/change a related_name "
|
||||||
'argument to the definition for field %s.') % (clash_name, field_name),
|
"argument to the definition for field '%s'.") % (clash_name, field_name),
|
||||||
obj=self,
|
obj=self,
|
||||||
id='E015',
|
id='fields.E303',
|
||||||
)
|
)
|
||||||
)
|
)
|
||||||
|
|
||||||
|
@ -223,22 +221,22 @@ class RelatedField(Field):
|
||||||
if clash_field.get_accessor_name() == rel_name:
|
if clash_field.get_accessor_name() == rel_name:
|
||||||
errors.append(
|
errors.append(
|
||||||
checks.Error(
|
checks.Error(
|
||||||
'Clash between accessors for %s and %s.' % (field_name, clash_name),
|
"Reverse accessor for '%s' clashes with reverse accessor for '%s'." % (field_name, clash_name),
|
||||||
hint=('Add or change a related_name argument '
|
hint=("Add or change a related_name argument "
|
||||||
'to the definition for %s or %s.') % (field_name, clash_name),
|
"to the definition for '%s' or '%s'.") % (field_name, clash_name),
|
||||||
obj=self,
|
obj=self,
|
||||||
id='E016',
|
id='fields.E304',
|
||||||
)
|
)
|
||||||
)
|
)
|
||||||
|
|
||||||
if clash_field.get_accessor_name() == rel_query_name:
|
if clash_field.get_accessor_name() == rel_query_name:
|
||||||
errors.append(
|
errors.append(
|
||||||
checks.Error(
|
checks.Error(
|
||||||
'Clash between reverse query names for %s and %s.' % (field_name, clash_name),
|
"Reverse query name for '%s' clashes with reverse query name for '%s'." % (field_name, clash_name),
|
||||||
hint=('Add or change a related_name argument '
|
hint=("Add or change a related_name argument "
|
||||||
'to the definition for %s or %s.') % (field_name, clash_name),
|
"to the definition for '%s' or '%s'.") % (field_name, clash_name),
|
||||||
obj=self,
|
obj=self,
|
||||||
id='E017',
|
id='fields.E305',
|
||||||
)
|
)
|
||||||
)
|
)
|
||||||
|
|
||||||
|
@ -1317,17 +1315,15 @@ class ForeignObject(RelatedField):
|
||||||
has_unique_field = any(rel_field.unique
|
has_unique_field = any(rel_field.unique
|
||||||
for rel_field in self.foreign_related_fields)
|
for rel_field in self.foreign_related_fields)
|
||||||
if not has_unique_field and len(self.foreign_related_fields) > 1:
|
if not has_unique_field and len(self.foreign_related_fields) > 1:
|
||||||
field_combination = ','.join(rel_field.name
|
field_combination = ', '.join("'%s'" % rel_field.name
|
||||||
for rel_field in self.foreign_related_fields)
|
for rel_field in self.foreign_related_fields)
|
||||||
model_name = self.rel.to.__name__
|
model_name = self.rel.to.__name__
|
||||||
return [
|
return [
|
||||||
checks.Error(
|
checks.Error(
|
||||||
('No unique=True constraint '
|
"None of the fields %s on model '%s' have a unique=True constraint." % (field_combination, model_name),
|
||||||
'on field combination "%s" under model %s.') % (field_combination, model_name),
|
hint=None,
|
||||||
hint=('Set unique=True argument on any of the fields '
|
|
||||||
'"%s" under model %s.') % (field_combination, model_name),
|
|
||||||
obj=self,
|
obj=self,
|
||||||
id='E018',
|
id='fields.E310',
|
||||||
)
|
)
|
||||||
]
|
]
|
||||||
elif not has_unique_field:
|
elif not has_unique_field:
|
||||||
|
@ -1335,11 +1331,11 @@ class ForeignObject(RelatedField):
|
||||||
model_name = self.rel.to.__name__
|
model_name = self.rel.to.__name__
|
||||||
return [
|
return [
|
||||||
checks.Error(
|
checks.Error(
|
||||||
('%s.%s must have unique=True '
|
("'%s.%s' must set unique=True "
|
||||||
'because it is referenced by a foreign key.') % (model_name, field_name),
|
"because it is referenced by a foreign key.") % (model_name, field_name),
|
||||||
hint=None,
|
hint=None,
|
||||||
obj=self,
|
obj=self,
|
||||||
id='E019',
|
id='fields.E311',
|
||||||
)
|
)
|
||||||
]
|
]
|
||||||
else:
|
else:
|
||||||
|
@ -1605,19 +1601,19 @@ class ForeignKey(ForeignObject):
|
||||||
if on_delete == SET_NULL and not self.null:
|
if on_delete == SET_NULL and not self.null:
|
||||||
return [
|
return [
|
||||||
checks.Error(
|
checks.Error(
|
||||||
'The field specifies on_delete=SET_NULL, but cannot be null.',
|
'Field specifies on_delete=SET_NULL, but cannot be null.',
|
||||||
hint='Set null=True argument on the field.',
|
hint='Set null=True argument on the field, or change the on_delete rule.',
|
||||||
obj=self,
|
obj=self,
|
||||||
id='E020',
|
id='fields.E320',
|
||||||
)
|
)
|
||||||
]
|
]
|
||||||
elif on_delete == SET_DEFAULT and not self.has_default():
|
elif on_delete == SET_DEFAULT and not self.has_default():
|
||||||
return [
|
return [
|
||||||
checks.Error(
|
checks.Error(
|
||||||
'The field specifies on_delete=SET_DEFAULT, but has no default value.',
|
'Field specifies on_delete=SET_DEFAULT, but has no default value.',
|
||||||
hint=None,
|
hint='Set a default value, or change the on_delete rule.',
|
||||||
obj=self,
|
obj=self,
|
||||||
id='E021',
|
id='fields.E321',
|
||||||
)
|
)
|
||||||
]
|
]
|
||||||
else:
|
else:
|
||||||
|
@ -1864,10 +1860,10 @@ class ManyToManyField(RelatedField):
|
||||||
if self.unique:
|
if self.unique:
|
||||||
return [
|
return [
|
||||||
checks.Error(
|
checks.Error(
|
||||||
'ManyToManyFields must not be unique.',
|
'ManyToManyFields cannot be unique.',
|
||||||
hint=None,
|
hint=None,
|
||||||
obj=self,
|
obj=self,
|
||||||
id='E022',
|
id='fields.E330',
|
||||||
)
|
)
|
||||||
]
|
]
|
||||||
return []
|
return []
|
||||||
|
@ -1879,13 +1875,11 @@ class ManyToManyField(RelatedField):
|
||||||
# The relationship model is not installed.
|
# The relationship model is not installed.
|
||||||
errors.append(
|
errors.append(
|
||||||
checks.Error(
|
checks.Error(
|
||||||
('The field specifies a many-to-many relation through model '
|
("Field specifies a many-to-many relation through model "
|
||||||
'%s, which has not been installed.') % self.rel.through,
|
"'%s', which has not been installed.") % self.rel.through,
|
||||||
hint=('Ensure that you did not misspell the model name and '
|
hint=None,
|
||||||
'the model is not abstract. Does your INSTALLED_APPS '
|
|
||||||
'setting contain the app where %s is defined?') % self.rel.through,
|
|
||||||
obj=self,
|
obj=self,
|
||||||
id='E023',
|
id='fields.E331',
|
||||||
)
|
)
|
||||||
)
|
)
|
||||||
|
|
||||||
|
@ -1914,7 +1908,7 @@ class ManyToManyField(RelatedField):
|
||||||
'Many-to-many fields with intermediate tables must not be symmetrical.',
|
'Many-to-many fields with intermediate tables must not be symmetrical.',
|
||||||
hint=None,
|
hint=None,
|
||||||
obj=self,
|
obj=self,
|
||||||
id='E024',
|
id='fields.E332',
|
||||||
)
|
)
|
||||||
)
|
)
|
||||||
|
|
||||||
|
@ -1926,12 +1920,12 @@ class ManyToManyField(RelatedField):
|
||||||
if seen_self > 2:
|
if seen_self > 2:
|
||||||
errors.append(
|
errors.append(
|
||||||
checks.Error(
|
checks.Error(
|
||||||
('The model is used as an intermediary model by '
|
("The model is used as an intermediate model by "
|
||||||
'%s, but it has more than two foreign keys '
|
"'%s', but it has more than two foreign keys "
|
||||||
'to %s, which is ambiguous and is not permitted.') % (self, from_model_name),
|
"to '%s', which is ambiguous.") % (self, from_model_name),
|
||||||
hint=None,
|
hint=None,
|
||||||
obj=self.rel.through,
|
obj=self.rel.through,
|
||||||
id='E025',
|
id='fields.E333',
|
||||||
)
|
)
|
||||||
)
|
)
|
||||||
|
|
||||||
|
@ -1945,41 +1939,41 @@ class ManyToManyField(RelatedField):
|
||||||
if seen_from > 1:
|
if seen_from > 1:
|
||||||
errors.append(
|
errors.append(
|
||||||
checks.Error(
|
checks.Error(
|
||||||
('The model is used as an intermediary model by '
|
("The model is used as an intermediate model by "
|
||||||
'%s, but it has more than one foreign key '
|
"'%s', but it has more than one foreign key "
|
||||||
'to %s, which is ambiguous and is not permitted.') % (self, from_model_name),
|
"from '%s', which is ambiguous.") % (self, from_model_name),
|
||||||
hint=('If you want to create a recursive relationship, '
|
hint=('If you want to create a recursive relationship, '
|
||||||
'use ForeignKey("self", symmetrical=False, '
|
'use ForeignKey("self", symmetrical=False, '
|
||||||
'through="%s").') % relationship_model_name,
|
'through="%s").') % relationship_model_name,
|
||||||
obj=self,
|
obj=self,
|
||||||
id='E026',
|
id='fields.E334',
|
||||||
)
|
)
|
||||||
)
|
)
|
||||||
|
|
||||||
if seen_to > 1:
|
if seen_to > 1:
|
||||||
errors.append(
|
errors.append(
|
||||||
checks.Error(
|
checks.Error(
|
||||||
('The model is used as an intermediary model by '
|
("The model is used as an intermediate model by "
|
||||||
'%s, but it has more than one foreign key '
|
"'%s', but it has more than one foreign key "
|
||||||
'to %s, which is ambiguous and is not permitted.') % (self, to_model_name),
|
"to '%s', which is ambiguous.") % (self, to_model_name),
|
||||||
hint=('If you want to create a recursive '
|
hint=('If you want to create a recursive '
|
||||||
'relationship, use ForeignKey("self", '
|
'relationship, use ForeignKey("self", '
|
||||||
'symmetrical=False, through="%s").') % relationship_model_name,
|
'symmetrical=False, through="%s").') % relationship_model_name,
|
||||||
obj=self,
|
obj=self,
|
||||||
id='E027',
|
id='fields.E335',
|
||||||
)
|
)
|
||||||
)
|
)
|
||||||
|
|
||||||
if seen_from == 0 or seen_to == 0:
|
if seen_from == 0 or seen_to == 0:
|
||||||
errors.append(
|
errors.append(
|
||||||
checks.Error(
|
checks.Error(
|
||||||
('The model is used as an intermediary model by '
|
("The model is used as an intermediate model by "
|
||||||
'%s, but it misses a foreign key to %s or %s.') % (
|
"'%s', but it does not have a foreign key to '%s' or '%s'.") % (
|
||||||
self, from_model_name, to_model_name
|
self, from_model_name, to_model_name
|
||||||
),
|
),
|
||||||
hint=None,
|
hint=None,
|
||||||
obj=self.rel.through,
|
obj=self.rel.through,
|
||||||
id='E028',
|
id='fields.E336',
|
||||||
)
|
)
|
||||||
)
|
)
|
||||||
return errors
|
return errors
|
||||||
|
|
|
@ -233,13 +233,11 @@ class GenericRelationshipTests(IsolatedModelsTestCase):
|
||||||
errors = Model.rel.field.check()
|
errors = Model.rel.field.check()
|
||||||
expected = [
|
expected = [
|
||||||
checks.Error(
|
checks.Error(
|
||||||
('The field has a relation with model MissingModel, '
|
("Field defines a relation with model 'MissingModel', "
|
||||||
'which has either not been installed or is abstract.'),
|
"which is either not installed, or is abstract."),
|
||||||
hint=('Ensure that you did not misspell the model name and '
|
hint=None,
|
||||||
'the model is not abstract. Does your INSTALLED_APPS '
|
|
||||||
'setting contain the app where MissingModel is defined?'),
|
|
||||||
obj=Model.rel.field,
|
obj=Model.rel.field,
|
||||||
id='E030',
|
id='fields.E300',
|
||||||
)
|
)
|
||||||
]
|
]
|
||||||
self.assertEqual(errors, expected)
|
self.assertEqual(errors, expected)
|
||||||
|
@ -295,12 +293,12 @@ class GenericRelationshipTests(IsolatedModelsTestCase):
|
||||||
errors = Model.rel.field.check()
|
errors = Model.rel.field.check()
|
||||||
expected = [
|
expected = [
|
||||||
checks.Error(
|
checks.Error(
|
||||||
('The field defines a relation with the model '
|
("Field defines a relation with the model "
|
||||||
'contenttypes_tests.SwappedModel, '
|
"'contenttypes_tests.SwappedModel', "
|
||||||
'which has been swapped out.'),
|
"which has been swapped out."),
|
||||||
hint='Update the relation to point at settings.TEST_SWAPPED_MODEL',
|
hint="Update the relation to point at 'settings.TEST_SWAPPED_MODEL'.",
|
||||||
obj=Model.rel.field,
|
obj=Model.rel.field,
|
||||||
id='E029',
|
id='fields.E301',
|
||||||
)
|
)
|
||||||
]
|
]
|
||||||
self.assertEqual(errors, expected)
|
self.assertEqual(errors, expected)
|
||||||
|
@ -317,10 +315,10 @@ class GenericRelationshipTests(IsolatedModelsTestCase):
|
||||||
errors = InvalidBookmark.tags_.field.check()
|
errors = InvalidBookmark.tags_.field.check()
|
||||||
expected = [
|
expected = [
|
||||||
checks.Error(
|
checks.Error(
|
||||||
'Field names must not end with underscores.',
|
'Field names must not end with an underscore.',
|
||||||
hint=None,
|
hint=None,
|
||||||
obj=InvalidBookmark.tags_.field,
|
obj=InvalidBookmark.tags_.field,
|
||||||
id='E001',
|
id='fields.E001',
|
||||||
)
|
)
|
||||||
]
|
]
|
||||||
self.assertEqual(errors, expected)
|
self.assertEqual(errors, expected)
|
||||||
|
|
|
@ -214,16 +214,16 @@ class FieldNamesTests(IsolatedModelsTestCase):
|
||||||
errors = Model.check()
|
errors = Model.check()
|
||||||
expected = [
|
expected = [
|
||||||
Error(
|
Error(
|
||||||
'Field names must not end with underscores.',
|
'Field names must not end with an underscore.',
|
||||||
hint=None,
|
hint=None,
|
||||||
obj=Model._meta.get_field('field_'),
|
obj=Model._meta.get_field('field_'),
|
||||||
id='E001',
|
id='fields.E001',
|
||||||
),
|
),
|
||||||
Error(
|
Error(
|
||||||
'Field names must not end with underscores.',
|
'Field names must not end with an underscore.',
|
||||||
hint=None,
|
hint=None,
|
||||||
obj=Model._meta.get_field('m2m_'),
|
obj=Model._meta.get_field('m2m_'),
|
||||||
id='E001',
|
id='fields.E001',
|
||||||
),
|
),
|
||||||
]
|
]
|
||||||
self.assertEqual(errors, expected)
|
self.assertEqual(errors, expected)
|
||||||
|
@ -238,7 +238,7 @@ class FieldNamesTests(IsolatedModelsTestCase):
|
||||||
'Field names must not contain "__".',
|
'Field names must not contain "__".',
|
||||||
hint=None,
|
hint=None,
|
||||||
obj=Model._meta.get_field('some__field'),
|
obj=Model._meta.get_field('some__field'),
|
||||||
id='E052',
|
id='fields.E002',
|
||||||
)
|
)
|
||||||
]
|
]
|
||||||
self.assertEqual(errors, expected)
|
self.assertEqual(errors, expected)
|
||||||
|
@ -250,10 +250,10 @@ class FieldNamesTests(IsolatedModelsTestCase):
|
||||||
errors = Model.check()
|
errors = Model.check()
|
||||||
expected = [
|
expected = [
|
||||||
Error(
|
Error(
|
||||||
'Cannot use "pk" as a field name since it is a reserved name.',
|
"'pk' is a reserved word that cannot be used as a field name.",
|
||||||
hint=None,
|
hint=None,
|
||||||
obj=Model._meta.get_field('pk'),
|
obj=Model._meta.get_field('pk'),
|
||||||
id='E051',
|
id='fields.E003',
|
||||||
)
|
)
|
||||||
]
|
]
|
||||||
self.assertEqual(errors, expected)
|
self.assertEqual(errors, expected)
|
||||||
|
|
|
@ -35,10 +35,10 @@ class AutoFieldTests(IsolatedModelsTestCase):
|
||||||
errors = field.check()
|
errors = field.check()
|
||||||
expected = [
|
expected = [
|
||||||
Error(
|
Error(
|
||||||
'The field must have primary_key=True, because it is an AutoField.',
|
'AutoFields must set primary_key=True.',
|
||||||
hint=None,
|
hint=None,
|
||||||
obj=field,
|
obj=field,
|
||||||
id='E048',
|
id='fields.E100',
|
||||||
),
|
),
|
||||||
]
|
]
|
||||||
self.assertEqual(errors, expected)
|
self.assertEqual(errors, expected)
|
||||||
|
@ -54,10 +54,10 @@ class BooleanFieldTests(IsolatedModelsTestCase):
|
||||||
errors = field.check()
|
errors = field.check()
|
||||||
expected = [
|
expected = [
|
||||||
Error(
|
Error(
|
||||||
'BooleanFields do not acceps null values.',
|
'BooleanFields do not accept null values.',
|
||||||
hint='Use a NullBooleanField instead.',
|
hint='Use a NullBooleanField instead.',
|
||||||
obj=field,
|
obj=field,
|
||||||
id='E037',
|
id='fields.E110',
|
||||||
),
|
),
|
||||||
]
|
]
|
||||||
self.assertEqual(errors, expected)
|
self.assertEqual(errors, expected)
|
||||||
|
@ -88,10 +88,10 @@ class CharFieldTests(IsolatedModelsTestCase):
|
||||||
errors = field.check()
|
errors = field.check()
|
||||||
expected = [
|
expected = [
|
||||||
Error(
|
Error(
|
||||||
'The field must have "max_length" attribute.',
|
"CharFields must define a 'max_length' attribute.",
|
||||||
hint=None,
|
hint=None,
|
||||||
obj=field,
|
obj=field,
|
||||||
id='E038',
|
id='fields.E120',
|
||||||
),
|
),
|
||||||
]
|
]
|
||||||
self.assertEqual(errors, expected)
|
self.assertEqual(errors, expected)
|
||||||
|
@ -104,10 +104,10 @@ class CharFieldTests(IsolatedModelsTestCase):
|
||||||
errors = field.check()
|
errors = field.check()
|
||||||
expected = [
|
expected = [
|
||||||
Error(
|
Error(
|
||||||
'"max_length" must be a positive integer.',
|
"'max_length' must be a positive integer.",
|
||||||
hint=None,
|
hint=None,
|
||||||
obj=field,
|
obj=field,
|
||||||
id='E039',
|
id='fields.E121',
|
||||||
),
|
),
|
||||||
]
|
]
|
||||||
self.assertEqual(errors, expected)
|
self.assertEqual(errors, expected)
|
||||||
|
@ -120,10 +120,10 @@ class CharFieldTests(IsolatedModelsTestCase):
|
||||||
errors = field.check()
|
errors = field.check()
|
||||||
expected = [
|
expected = [
|
||||||
Error(
|
Error(
|
||||||
'"max_length" must be a positive integer.',
|
"'max_length' must be a positive integer.",
|
||||||
hint=None,
|
hint=None,
|
||||||
obj=field,
|
obj=field,
|
||||||
id='E039',
|
id='fields.E121',
|
||||||
),
|
),
|
||||||
]
|
]
|
||||||
self.assertEqual(errors, expected)
|
self.assertEqual(errors, expected)
|
||||||
|
@ -136,10 +136,10 @@ class CharFieldTests(IsolatedModelsTestCase):
|
||||||
errors = field.check()
|
errors = field.check()
|
||||||
expected = [
|
expected = [
|
||||||
Error(
|
Error(
|
||||||
'"choices" must be an iterable (e.g., a list or tuple).',
|
"'choices' must be an iterable (e.g., a list or tuple).",
|
||||||
hint=None,
|
hint=None,
|
||||||
obj=field,
|
obj=field,
|
||||||
id='E033',
|
id='fields.E004',
|
||||||
),
|
),
|
||||||
]
|
]
|
||||||
self.assertEqual(errors, expected)
|
self.assertEqual(errors, expected)
|
||||||
|
@ -152,12 +152,10 @@ class CharFieldTests(IsolatedModelsTestCase):
|
||||||
errors = field.check()
|
errors = field.check()
|
||||||
expected = [
|
expected = [
|
||||||
Error(
|
Error(
|
||||||
('All "choices" elements must be a tuple of two elements '
|
"'choices' must be an iterable containing (actual value, human readable name) tuples.",
|
||||||
'(the first one is the actual value to be stored '
|
|
||||||
'and the second element is the human-readable name).'),
|
|
||||||
hint=None,
|
hint=None,
|
||||||
obj=field,
|
obj=field,
|
||||||
id='E034',
|
id='fields.E005',
|
||||||
),
|
),
|
||||||
]
|
]
|
||||||
self.assertEqual(errors, expected)
|
self.assertEqual(errors, expected)
|
||||||
|
@ -170,10 +168,10 @@ class CharFieldTests(IsolatedModelsTestCase):
|
||||||
errors = field.check()
|
errors = field.check()
|
||||||
expected = [
|
expected = [
|
||||||
Error(
|
Error(
|
||||||
'"db_index" must be either None, True or False.',
|
"'db_index' must be None, True or False.",
|
||||||
hint=None,
|
hint=None,
|
||||||
obj=field,
|
obj=field,
|
||||||
id='E035',
|
id='fields.E006',
|
||||||
),
|
),
|
||||||
]
|
]
|
||||||
self.assertEqual(errors, expected)
|
self.assertEqual(errors, expected)
|
||||||
|
@ -210,16 +208,16 @@ class DecimalFieldTests(IsolatedModelsTestCase):
|
||||||
errors = field.check()
|
errors = field.check()
|
||||||
expected = [
|
expected = [
|
||||||
Error(
|
Error(
|
||||||
'The field requires a "decimal_places" attribute.',
|
"DecimalFields must define a 'decimal_places' attribute.",
|
||||||
hint=None,
|
hint=None,
|
||||||
obj=field,
|
obj=field,
|
||||||
id='E041',
|
id='fields.E130',
|
||||||
),
|
),
|
||||||
Error(
|
Error(
|
||||||
'The field requires a "max_digits" attribute.',
|
"DecimalFields must define a 'max_digits' attribute.",
|
||||||
hint=None,
|
hint=None,
|
||||||
obj=field,
|
obj=field,
|
||||||
id='E043',
|
id='fields.E132',
|
||||||
),
|
),
|
||||||
]
|
]
|
||||||
self.assertEqual(errors, expected)
|
self.assertEqual(errors, expected)
|
||||||
|
@ -232,16 +230,16 @@ class DecimalFieldTests(IsolatedModelsTestCase):
|
||||||
errors = field.check()
|
errors = field.check()
|
||||||
expected = [
|
expected = [
|
||||||
Error(
|
Error(
|
||||||
'"decimal_places" attribute must be a non-negative integer.',
|
"'decimal_places' must be a non-negative integer.",
|
||||||
hint=None,
|
hint=None,
|
||||||
obj=field,
|
obj=field,
|
||||||
id='E042',
|
id='fields.E131',
|
||||||
),
|
),
|
||||||
Error(
|
Error(
|
||||||
'"max_digits" attribute must be a positive integer.',
|
"'max_digits' must be a positive integer.",
|
||||||
hint=None,
|
hint=None,
|
||||||
obj=field,
|
obj=field,
|
||||||
id='E044',
|
id='fields.E133',
|
||||||
),
|
),
|
||||||
]
|
]
|
||||||
self.assertEqual(errors, expected)
|
self.assertEqual(errors, expected)
|
||||||
|
@ -254,16 +252,16 @@ class DecimalFieldTests(IsolatedModelsTestCase):
|
||||||
errors = field.check()
|
errors = field.check()
|
||||||
expected = [
|
expected = [
|
||||||
Error(
|
Error(
|
||||||
'"decimal_places" attribute must be a non-negative integer.',
|
"'decimal_places' must be a non-negative integer.",
|
||||||
hint=None,
|
hint=None,
|
||||||
obj=field,
|
obj=field,
|
||||||
id='E042',
|
id='fields.E131',
|
||||||
),
|
),
|
||||||
Error(
|
Error(
|
||||||
'"max_digits" attribute must be a positive integer.',
|
"'max_digits' must be a positive integer.",
|
||||||
hint=None,
|
hint=None,
|
||||||
obj=field,
|
obj=field,
|
||||||
id='E044',
|
id='fields.E133',
|
||||||
),
|
),
|
||||||
]
|
]
|
||||||
self.assertEqual(errors, expected)
|
self.assertEqual(errors, expected)
|
||||||
|
@ -276,10 +274,10 @@ class DecimalFieldTests(IsolatedModelsTestCase):
|
||||||
errors = field.check()
|
errors = field.check()
|
||||||
expected = [
|
expected = [
|
||||||
Error(
|
Error(
|
||||||
'"max_digits" must be greater or equal to "decimal_places".',
|
"'max_digits' must be greater or equal to 'decimal_places'.",
|
||||||
hint=None,
|
hint=None,
|
||||||
obj=field,
|
obj=field,
|
||||||
id='E040',
|
id='fields.E134',
|
||||||
),
|
),
|
||||||
]
|
]
|
||||||
self.assertEqual(errors, expected)
|
self.assertEqual(errors, expected)
|
||||||
|
@ -313,10 +311,10 @@ class FileFieldTests(IsolatedModelsTestCase):
|
||||||
errors = field.check()
|
errors = field.check()
|
||||||
expected = [
|
expected = [
|
||||||
Error(
|
Error(
|
||||||
'"unique" is not a valid argument for FileField.',
|
"'unique' is not a valid argument for a FileField.",
|
||||||
hint=None,
|
hint=None,
|
||||||
obj=field,
|
obj=field,
|
||||||
id='E049',
|
id='fields.E200',
|
||||||
)
|
)
|
||||||
]
|
]
|
||||||
self.assertEqual(errors, expected)
|
self.assertEqual(errors, expected)
|
||||||
|
@ -329,10 +327,10 @@ class FileFieldTests(IsolatedModelsTestCase):
|
||||||
errors = field.check()
|
errors = field.check()
|
||||||
expected = [
|
expected = [
|
||||||
Error(
|
Error(
|
||||||
'"primary_key" is not a valid argument for FileField.',
|
"'primary_key' is not a valid argument for a FileField.",
|
||||||
hint=None,
|
hint=None,
|
||||||
obj=field,
|
obj=field,
|
||||||
id='E050',
|
id='fields.E201',
|
||||||
)
|
)
|
||||||
]
|
]
|
||||||
self.assertEqual(errors, expected)
|
self.assertEqual(errors, expected)
|
||||||
|
@ -348,10 +346,10 @@ class FilePathFieldTests(IsolatedModelsTestCase):
|
||||||
errors = field.check()
|
errors = field.check()
|
||||||
expected = [
|
expected = [
|
||||||
Error(
|
Error(
|
||||||
'The field must have either "allow_files" or "allow_folders" set to True.',
|
"FilePathFields must have either 'allow_files' or 'allow_folders' set to True.",
|
||||||
hint=None,
|
hint=None,
|
||||||
obj=field,
|
obj=field,
|
||||||
id='E045',
|
id='fields.E140',
|
||||||
),
|
),
|
||||||
]
|
]
|
||||||
self.assertEqual(errors, expected)
|
self.assertEqual(errors, expected)
|
||||||
|
@ -367,11 +365,11 @@ class GenericIPAddressFieldTests(IsolatedModelsTestCase):
|
||||||
errors = field.check()
|
errors = field.check()
|
||||||
expected = [
|
expected = [
|
||||||
Error(
|
Error(
|
||||||
('The field cannot accept blank values if null values '
|
('GenericIPAddressFields cannot have blank=True if null=False, '
|
||||||
'are not allowed, as blank values are stored as null.'),
|
'as blank values are stored as nulls.'),
|
||||||
hint=None,
|
hint=None,
|
||||||
obj=field,
|
obj=field,
|
||||||
id='E046',
|
id='fields.E150',
|
||||||
),
|
),
|
||||||
]
|
]
|
||||||
self.assertEqual(errors, expected)
|
self.assertEqual(errors, expected)
|
||||||
|
@ -394,11 +392,11 @@ class ImageFieldTests(IsolatedModelsTestCase):
|
||||||
errors = field.check()
|
errors = field.check()
|
||||||
expected = [] if pillow_installed else [
|
expected = [] if pillow_installed else [
|
||||||
Error(
|
Error(
|
||||||
'To use ImageFields, Pillow must be installed.',
|
'Cannot use ImageField because Pillow is not installed.',
|
||||||
hint=('Get Pillow at https://pypi.python.org/pypi/Pillow '
|
hint=('Get Pillow at https://pypi.python.org/pypi/Pillow '
|
||||||
'or run command "pip install pillow".'),
|
'or run command "pip install pillow".'),
|
||||||
obj=field,
|
obj=field,
|
||||||
id='E032',
|
id='fields.E210',
|
||||||
),
|
),
|
||||||
]
|
]
|
||||||
self.assertEqual(errors, expected)
|
self.assertEqual(errors, expected)
|
||||||
|
|
|
@ -34,13 +34,11 @@ class RelativeFieldTests(IsolatedModelsTestCase):
|
||||||
errors = field.check()
|
errors = field.check()
|
||||||
expected = [
|
expected = [
|
||||||
Error(
|
Error(
|
||||||
('The field has a relation with model Rel1, '
|
("Field defines a relation with model 'Rel1', "
|
||||||
'which has either not been installed or is abstract.'),
|
"which is either not installed, or is abstract."),
|
||||||
hint=('Ensure that you did not misspell the model name and '
|
hint=None,
|
||||||
'the model is not abstract. Does your INSTALLED_APPS '
|
|
||||||
'setting contain the app where Rel1 is defined?'),
|
|
||||||
obj=field,
|
obj=field,
|
||||||
id='E030',
|
id='fields.E300',
|
||||||
),
|
),
|
||||||
]
|
]
|
||||||
self.assertEqual(errors, expected)
|
self.assertEqual(errors, expected)
|
||||||
|
@ -53,13 +51,11 @@ class RelativeFieldTests(IsolatedModelsTestCase):
|
||||||
errors = field.check(from_model=Model)
|
errors = field.check(from_model=Model)
|
||||||
expected = [
|
expected = [
|
||||||
Error(
|
Error(
|
||||||
('The field has a relation with model Rel2, '
|
("Field defines a relation with model 'Rel2', "
|
||||||
'which has either not been installed or is abstract.'),
|
"which is either not installed, or is abstract."),
|
||||||
hint=('Ensure that you did not misspell the model name and '
|
hint=None,
|
||||||
'the model is not abstract. Does your INSTALLED_APPS '
|
|
||||||
'setting contain the app where Rel2 is defined?'),
|
|
||||||
obj=field,
|
obj=field,
|
||||||
id='E030',
|
id='fields.E300',
|
||||||
),
|
),
|
||||||
]
|
]
|
||||||
self.assertEqual(errors, expected)
|
self.assertEqual(errors, expected)
|
||||||
|
@ -83,15 +79,14 @@ class RelativeFieldTests(IsolatedModelsTestCase):
|
||||||
errors = field.check(from_model=Group)
|
errors = field.check(from_model=Group)
|
||||||
expected = [
|
expected = [
|
||||||
Error(
|
Error(
|
||||||
('The model is used as an intermediary model by '
|
("The model is used as an intermediate model by "
|
||||||
'invalid_models_tests.Group.field, but it has more than one '
|
"'invalid_models_tests.Group.field', but it has more than one "
|
||||||
'foreign key to Person, '
|
"foreign key to 'Person', which is ambiguous."),
|
||||||
'which is ambiguous and is not permitted.'),
|
|
||||||
hint=('If you want to create a recursive relationship, use '
|
hint=('If you want to create a recursive relationship, use '
|
||||||
'ForeignKey("self", symmetrical=False, '
|
'ForeignKey("self", symmetrical=False, '
|
||||||
'through="AmbiguousRelationship").'),
|
'through="AmbiguousRelationship").'),
|
||||||
obj=field,
|
obj=field,
|
||||||
id='E027',
|
id='fields.E335',
|
||||||
),
|
),
|
||||||
]
|
]
|
||||||
self.assertEqual(errors, expected)
|
self.assertEqual(errors, expected)
|
||||||
|
@ -116,12 +111,12 @@ class RelativeFieldTests(IsolatedModelsTestCase):
|
||||||
errors = field.check(from_model=Group)
|
errors = field.check(from_model=Group)
|
||||||
expected = [
|
expected = [
|
||||||
Error(
|
Error(
|
||||||
('The model is used as an intermediary model by '
|
("The model is used as an intermediate model by "
|
||||||
'invalid_models_tests.Group.members, but it misses '
|
"'invalid_models_tests.Group.members', but it does not "
|
||||||
'a foreign key to Group or Person.'),
|
"have a foreign key to 'Group' or 'Person'."),
|
||||||
hint=None,
|
hint=None,
|
||||||
obj=InvalidRelationship,
|
obj=InvalidRelationship,
|
||||||
id='E028',
|
id='fields.E336',
|
||||||
),
|
),
|
||||||
]
|
]
|
||||||
self.assertEqual(errors, expected)
|
self.assertEqual(errors, expected)
|
||||||
|
@ -142,12 +137,12 @@ class RelativeFieldTests(IsolatedModelsTestCase):
|
||||||
errors = field.check(from_model=Group)
|
errors = field.check(from_model=Group)
|
||||||
expected = [
|
expected = [
|
||||||
Error(
|
Error(
|
||||||
('The model is used as an intermediary model by '
|
("The model is used as an intermediate model by "
|
||||||
'invalid_models_tests.Group.members, but it misses '
|
"'invalid_models_tests.Group.members', but it does not have "
|
||||||
'a foreign key to Group or Person.'),
|
"a foreign key to 'Group' or 'Person'."),
|
||||||
hint=None,
|
hint=None,
|
||||||
obj=InvalidRelationship,
|
obj=InvalidRelationship,
|
||||||
id='E028',
|
id='fields.E336',
|
||||||
),
|
),
|
||||||
]
|
]
|
||||||
self.assertEqual(errors, expected)
|
self.assertEqual(errors, expected)
|
||||||
|
@ -164,13 +159,11 @@ class RelativeFieldTests(IsolatedModelsTestCase):
|
||||||
errors = field.check(from_model=Group)
|
errors = field.check(from_model=Group)
|
||||||
expected = [
|
expected = [
|
||||||
Error(
|
Error(
|
||||||
('The field specifies a many-to-many relation through model '
|
("Field specifies a many-to-many relation through model "
|
||||||
'MissingM2MModel, which has not been installed.'),
|
"'MissingM2MModel', which has not been installed."),
|
||||||
hint=('Ensure that you did not misspell the model name and '
|
hint=None,
|
||||||
'the model is not abstract. Does your INSTALLED_APPS '
|
|
||||||
'setting contain the app where MissingM2MModel is defined?'),
|
|
||||||
obj=field,
|
obj=field,
|
||||||
id='E023',
|
id='fields.E331',
|
||||||
),
|
),
|
||||||
]
|
]
|
||||||
self.assertEqual(errors, expected)
|
self.assertEqual(errors, expected)
|
||||||
|
@ -191,7 +184,7 @@ class RelativeFieldTests(IsolatedModelsTestCase):
|
||||||
'Many-to-many fields with intermediate tables must not be symmetrical.',
|
'Many-to-many fields with intermediate tables must not be symmetrical.',
|
||||||
hint=None,
|
hint=None,
|
||||||
obj=field,
|
obj=field,
|
||||||
id='E024',
|
id='fields.E332',
|
||||||
),
|
),
|
||||||
]
|
]
|
||||||
self.assertEqual(errors, expected)
|
self.assertEqual(errors, expected)
|
||||||
|
@ -210,13 +203,12 @@ class RelativeFieldTests(IsolatedModelsTestCase):
|
||||||
errors = field.check(from_model=Person)
|
errors = field.check(from_model=Person)
|
||||||
expected = [
|
expected = [
|
||||||
Error(
|
Error(
|
||||||
('The model is used as an intermediary model by '
|
("The model is used as an intermediate model by "
|
||||||
'invalid_models_tests.Person.friends, but it has more than two '
|
"'invalid_models_tests.Person.friends', but it has more than two "
|
||||||
'foreign keys to Person, which is ambiguous and '
|
"foreign keys to 'Person', which is ambiguous."),
|
||||||
'is not permitted.'),
|
|
||||||
hint=None,
|
hint=None,
|
||||||
obj=InvalidRelationship,
|
obj=InvalidRelationship,
|
||||||
id='E025',
|
id='fields.E333',
|
||||||
),
|
),
|
||||||
]
|
]
|
||||||
self.assertEqual(errors, expected)
|
self.assertEqual(errors, expected)
|
||||||
|
@ -238,7 +230,7 @@ class RelativeFieldTests(IsolatedModelsTestCase):
|
||||||
'Many-to-many fields with intermediate tables must not be symmetrical.',
|
'Many-to-many fields with intermediate tables must not be symmetrical.',
|
||||||
hint=None,
|
hint=None,
|
||||||
obj=field,
|
obj=field,
|
||||||
id='E024',
|
id='fields.E332',
|
||||||
),
|
),
|
||||||
]
|
]
|
||||||
self.assertEqual(errors, expected)
|
self.assertEqual(errors, expected)
|
||||||
|
@ -255,13 +247,11 @@ class RelativeFieldTests(IsolatedModelsTestCase):
|
||||||
errors = field.check()
|
errors = field.check()
|
||||||
expected = [
|
expected = [
|
||||||
Error(
|
Error(
|
||||||
('The field has a relation with model AbstractModel, '
|
("Field defines a relation with model 'AbstractModel', "
|
||||||
'which has either not been installed or is abstract.'),
|
"which is either not installed, or is abstract."),
|
||||||
hint=('Ensure that you did not misspell the model name and '
|
hint=None,
|
||||||
'the model is not abstract. Does your INSTALLED_APPS '
|
|
||||||
'setting contain the app where AbstractModel is defined?'),
|
|
||||||
obj=field,
|
obj=field,
|
||||||
id='E030',
|
id='fields.E300',
|
||||||
),
|
),
|
||||||
]
|
]
|
||||||
self.assertEqual(errors, expected)
|
self.assertEqual(errors, expected)
|
||||||
|
@ -278,13 +268,11 @@ class RelativeFieldTests(IsolatedModelsTestCase):
|
||||||
errors = field.check(from_model=Model)
|
errors = field.check(from_model=Model)
|
||||||
expected = [
|
expected = [
|
||||||
Error(
|
Error(
|
||||||
('The field has a relation with model AbstractModel, '
|
("Field defines a relation with model 'AbstractModel', "
|
||||||
'which has either not been installed or is abstract.'),
|
"which is either not installed, or is abstract."),
|
||||||
hint=('Ensure that you did not misspell the model name and '
|
hint=None,
|
||||||
'the model is not abstract. Does your INSTALLED_APPS '
|
|
||||||
'setting contain the app where AbstractModel is defined?'),
|
|
||||||
obj=field,
|
obj=field,
|
||||||
id='E030',
|
id='fields.E300',
|
||||||
),
|
),
|
||||||
]
|
]
|
||||||
self.assertEqual(errors, expected)
|
self.assertEqual(errors, expected)
|
||||||
|
@ -300,10 +288,10 @@ class RelativeFieldTests(IsolatedModelsTestCase):
|
||||||
errors = field.check(from_model=Group)
|
errors = field.check(from_model=Group)
|
||||||
expected = [
|
expected = [
|
||||||
Error(
|
Error(
|
||||||
'ManyToManyFields must not be unique.',
|
'ManyToManyFields cannot be unique.',
|
||||||
hint=None,
|
hint=None,
|
||||||
obj=field,
|
obj=field,
|
||||||
id='E022',
|
id='fields.E330',
|
||||||
),
|
),
|
||||||
]
|
]
|
||||||
self.assertEqual(errors, expected)
|
self.assertEqual(errors, expected)
|
||||||
|
@ -319,10 +307,10 @@ class RelativeFieldTests(IsolatedModelsTestCase):
|
||||||
errors = field.check()
|
errors = field.check()
|
||||||
expected = [
|
expected = [
|
||||||
Error(
|
Error(
|
||||||
'Target.bad must have unique=True because it is referenced by a foreign key.',
|
"'Target.bad' must set unique=True because it is referenced by a foreign key.",
|
||||||
hint=None,
|
hint=None,
|
||||||
obj=field,
|
obj=field,
|
||||||
id='E019',
|
id='fields.E311',
|
||||||
),
|
),
|
||||||
]
|
]
|
||||||
self.assertEqual(errors, expected)
|
self.assertEqual(errors, expected)
|
||||||
|
@ -338,10 +326,10 @@ class RelativeFieldTests(IsolatedModelsTestCase):
|
||||||
errors = field.check()
|
errors = field.check()
|
||||||
expected = [
|
expected = [
|
||||||
Error(
|
Error(
|
||||||
'Target.bad must have unique=True because it is referenced by a foreign key.',
|
"'Target.bad' must set unique=True because it is referenced by a foreign key.",
|
||||||
hint=None,
|
hint=None,
|
||||||
obj=field,
|
obj=field,
|
||||||
id='E019',
|
id='fields.E311',
|
||||||
),
|
),
|
||||||
]
|
]
|
||||||
self.assertEqual(errors, expected)
|
self.assertEqual(errors, expected)
|
||||||
|
@ -364,12 +352,11 @@ class RelativeFieldTests(IsolatedModelsTestCase):
|
||||||
errors = field.check()
|
errors = field.check()
|
||||||
expected = [
|
expected = [
|
||||||
Error(
|
Error(
|
||||||
('No unique=True constraint on field combination '
|
("None of the fields 'country_id', 'city_id' on model 'Person' "
|
||||||
'"country_id,city_id" under model Person.'),
|
"have a unique=True constraint."),
|
||||||
hint=('Set unique=True argument on any of the fields '
|
hint=None,
|
||||||
'"country_id,city_id" under model Person.'),
|
|
||||||
obj=field,
|
obj=field,
|
||||||
id='E018',
|
id='fields.E310',
|
||||||
)
|
)
|
||||||
]
|
]
|
||||||
self.assertEqual(errors, expected)
|
self.assertEqual(errors, expected)
|
||||||
|
@ -386,10 +373,10 @@ class RelativeFieldTests(IsolatedModelsTestCase):
|
||||||
errors = field.check()
|
errors = field.check()
|
||||||
expected = [
|
expected = [
|
||||||
Error(
|
Error(
|
||||||
'The field specifies on_delete=SET_NULL, but cannot be null.',
|
'Field specifies on_delete=SET_NULL, but cannot be null.',
|
||||||
hint='Set null=True argument on the field.',
|
hint='Set null=True argument on the field, or change the on_delete rule.',
|
||||||
obj=field,
|
obj=field,
|
||||||
id='E020',
|
id='fields.E320',
|
||||||
),
|
),
|
||||||
]
|
]
|
||||||
self.assertEqual(errors, expected)
|
self.assertEqual(errors, expected)
|
||||||
|
@ -406,10 +393,10 @@ class RelativeFieldTests(IsolatedModelsTestCase):
|
||||||
errors = field.check()
|
errors = field.check()
|
||||||
expected = [
|
expected = [
|
||||||
Error(
|
Error(
|
||||||
'The field specifies on_delete=SET_DEFAULT, but has no default value.',
|
'Field specifies on_delete=SET_DEFAULT, but has no default value.',
|
||||||
hint=None,
|
hint='Set a default value, or change the on_delete rule.',
|
||||||
obj=field,
|
obj=field,
|
||||||
id='E021',
|
id='fields.E321',
|
||||||
),
|
),
|
||||||
]
|
]
|
||||||
self.assertEqual(errors, expected)
|
self.assertEqual(errors, expected)
|
||||||
|
@ -424,9 +411,9 @@ class RelativeFieldTests(IsolatedModelsTestCase):
|
||||||
expected = [
|
expected = [
|
||||||
Error(
|
Error(
|
||||||
'Primary keys must not have null=True.',
|
'Primary keys must not have null=True.',
|
||||||
hint='Set null=False on the field or remove primary_key=True argument.',
|
hint='Set null=False on the field, or remove primary_key=True argument.',
|
||||||
obj=field,
|
obj=field,
|
||||||
id='E036',
|
id='fields.E007',
|
||||||
),
|
),
|
||||||
]
|
]
|
||||||
self.assertEqual(errors, expected)
|
self.assertEqual(errors, expected)
|
||||||
|
@ -489,10 +476,10 @@ class RelativeFieldTests(IsolatedModelsTestCase):
|
||||||
]
|
]
|
||||||
|
|
||||||
expected_error = Error(
|
expected_error = Error(
|
||||||
('The field defines a relation with the model '
|
("Field defines a relation with the model "
|
||||||
'invalid_models_tests.SwappedModel, which has been swapped out.'),
|
"'invalid_models_tests.SwappedModel', which has been swapped out."),
|
||||||
hint='Update the relation to point at settings.TEST_SWAPPED_MODEL',
|
hint="Update the relation to point at 'settings.TEST_SWAPPED_MODEL'.",
|
||||||
id='E029',
|
id='fields.E301',
|
||||||
)
|
)
|
||||||
|
|
||||||
for field in fields:
|
for field in fields:
|
||||||
|
@ -546,12 +533,12 @@ class AccessorClashTests(IsolatedModelsTestCase):
|
||||||
errors = Model.check()
|
errors = Model.check()
|
||||||
expected = [
|
expected = [
|
||||||
Error(
|
Error(
|
||||||
'Accessor for field Model.rel clashes with field Target.model_set.',
|
"Reverse accessor for 'Model.rel' clashes with field name 'Target.model_set'.",
|
||||||
hint=('Rename field Target.model_set or add/change '
|
hint=("Rename field 'Target.model_set', or add/change "
|
||||||
'a related_name argument to the definition '
|
"a related_name argument to the definition "
|
||||||
'for field Model.rel.'),
|
"for field 'Model.rel'."),
|
||||||
obj=Model._meta.get_field('rel'),
|
obj=Model._meta.get_field('rel'),
|
||||||
id='E014',
|
id='fields.E302',
|
||||||
),
|
),
|
||||||
]
|
]
|
||||||
self.assertEqual(errors, expected)
|
self.assertEqual(errors, expected)
|
||||||
|
@ -567,18 +554,18 @@ class AccessorClashTests(IsolatedModelsTestCase):
|
||||||
errors = Model.check()
|
errors = Model.check()
|
||||||
expected = [
|
expected = [
|
||||||
Error(
|
Error(
|
||||||
'Clash between accessors for Model.foreign and Model.m2m.',
|
"Reverse accessor for 'Model.foreign' clashes with reverse accessor for 'Model.m2m'.",
|
||||||
hint=('Add or change a related_name argument to the definition '
|
hint=("Add or change a related_name argument to the definition "
|
||||||
'for Model.foreign or Model.m2m.'),
|
"for 'Model.foreign' or 'Model.m2m'."),
|
||||||
obj=Model._meta.get_field('foreign'),
|
obj=Model._meta.get_field('foreign'),
|
||||||
id='E016',
|
id='fields.E304',
|
||||||
),
|
),
|
||||||
Error(
|
Error(
|
||||||
'Clash between accessors for Model.m2m and Model.foreign.',
|
"Reverse accessor for 'Model.m2m' clashes with reverse accessor for 'Model.foreign'.",
|
||||||
hint=('Add or change a related_name argument to the definition '
|
hint=("Add or change a related_name argument to the definition "
|
||||||
'for Model.m2m or Model.foreign.'),
|
"for 'Model.m2m' or 'Model.foreign'."),
|
||||||
obj=Model._meta.get_field('m2m'),
|
obj=Model._meta.get_field('m2m'),
|
||||||
id='E016',
|
id='fields.E304',
|
||||||
),
|
),
|
||||||
]
|
]
|
||||||
self.assertEqual(errors, expected)
|
self.assertEqual(errors, expected)
|
||||||
|
@ -602,12 +589,12 @@ class AccessorClashTests(IsolatedModelsTestCase):
|
||||||
errors = Model.check()
|
errors = Model.check()
|
||||||
expected = [
|
expected = [
|
||||||
Error(
|
Error(
|
||||||
'Accessor for field Model.children clashes with field Child.m2m_clash.',
|
"Reverse accessor for 'Model.children' clashes with field name 'Child.m2m_clash'.",
|
||||||
hint=('Rename field Child.m2m_clash or add/change '
|
hint=("Rename field 'Child.m2m_clash', or add/change "
|
||||||
'a related_name argument to the definition '
|
"a related_name argument to the definition "
|
||||||
'for field Model.children.'),
|
"for field 'Model.children'."),
|
||||||
obj=Model._meta.get_field('children'),
|
obj=Model._meta.get_field('children'),
|
||||||
id='E014',
|
id='fields.E302',
|
||||||
)
|
)
|
||||||
]
|
]
|
||||||
self.assertEqual(errors, expected)
|
self.assertEqual(errors, expected)
|
||||||
|
@ -658,12 +645,12 @@ class ReverseQueryNameClashTests(IsolatedModelsTestCase):
|
||||||
errors = Model.check()
|
errors = Model.check()
|
||||||
expected = [
|
expected = [
|
||||||
Error(
|
Error(
|
||||||
'Reverse query name for field Model.rel clashes with field Target.model.',
|
"Reverse query name for 'Model.rel' clashes with field name 'Target.model'.",
|
||||||
hint=('Rename field Target.model or add/change '
|
hint=("Rename field 'Target.model', or add/change "
|
||||||
'a related_name argument to the definition '
|
"a related_name argument to the definition "
|
||||||
'for field Model.rel.'),
|
"for field 'Model.rel'."),
|
||||||
obj=Model._meta.get_field('rel'),
|
obj=Model._meta.get_field('rel'),
|
||||||
id='E015',
|
id='fields.E303',
|
||||||
),
|
),
|
||||||
]
|
]
|
||||||
self.assertEqual(errors, expected)
|
self.assertEqual(errors, expected)
|
||||||
|
@ -714,20 +701,20 @@ class ExplicitRelatedNameClashTests(IsolatedModelsTestCase):
|
||||||
errors = Model.check()
|
errors = Model.check()
|
||||||
expected = [
|
expected = [
|
||||||
Error(
|
Error(
|
||||||
'Accessor for field Model.rel clashes with field Target.clash.',
|
"Reverse accessor for 'Model.rel' clashes with field name 'Target.clash'.",
|
||||||
hint=('Rename field Target.clash or add/change '
|
hint=("Rename field 'Target.clash', or add/change "
|
||||||
'a related_name argument to the definition '
|
"a related_name argument to the definition "
|
||||||
'for field Model.rel.'),
|
"for field 'Model.rel'."),
|
||||||
obj=Model._meta.get_field('rel'),
|
obj=Model._meta.get_field('rel'),
|
||||||
id='E014',
|
id='fields.E302',
|
||||||
),
|
),
|
||||||
Error(
|
Error(
|
||||||
'Reverse query name for field Model.rel clashes with field Target.clash.',
|
"Reverse query name for 'Model.rel' clashes with field name 'Target.clash'.",
|
||||||
hint=('Rename field Target.clash or add/change '
|
hint=("Rename field 'Target.clash', or add/change "
|
||||||
'a related_name argument to the definition '
|
"a related_name argument to the definition "
|
||||||
'for field Model.rel.'),
|
"for field 'Model.rel'."),
|
||||||
obj=Model._meta.get_field('rel'),
|
obj=Model._meta.get_field('rel'),
|
||||||
id='E015',
|
id='fields.E303',
|
||||||
),
|
),
|
||||||
]
|
]
|
||||||
self.assertEqual(errors, expected)
|
self.assertEqual(errors, expected)
|
||||||
|
@ -784,11 +771,11 @@ class ExplicitRelatedQueryNameClashTests(IsolatedModelsTestCase):
|
||||||
errors = Model.check()
|
errors = Model.check()
|
||||||
expected = [
|
expected = [
|
||||||
Error(
|
Error(
|
||||||
'Reverse query name for field Model.rel clashes with field Target.clash.',
|
"Reverse query name for 'Model.rel' clashes with field name 'Target.clash'.",
|
||||||
hint=('Rename field Target.clash or add/change a related_name '
|
hint=("Rename field 'Target.clash', or add/change a related_name "
|
||||||
'argument to the definition for field Model.rel.'),
|
"argument to the definition for field 'Model.rel'."),
|
||||||
obj=Model._meta.get_field('rel'),
|
obj=Model._meta.get_field('rel'),
|
||||||
id='E015',
|
id='fields.E303',
|
||||||
),
|
),
|
||||||
]
|
]
|
||||||
self.assertEqual(errors, expected)
|
self.assertEqual(errors, expected)
|
||||||
|
@ -804,18 +791,18 @@ class SelfReferentialM2MClashTests(IsolatedModelsTestCase):
|
||||||
errors = Model.check()
|
errors = Model.check()
|
||||||
expected = [
|
expected = [
|
||||||
Error(
|
Error(
|
||||||
'Clash between accessors for Model.first_m2m and Model.second_m2m.',
|
"Reverse accessor for 'Model.first_m2m' clashes with reverse accessor for 'Model.second_m2m'.",
|
||||||
hint=('Add or change a related_name argument to the definition '
|
hint=("Add or change a related_name argument to the definition "
|
||||||
'for Model.first_m2m or Model.second_m2m.'),
|
"for 'Model.first_m2m' or 'Model.second_m2m'."),
|
||||||
obj=Model._meta.get_field('first_m2m'),
|
obj=Model._meta.get_field('first_m2m'),
|
||||||
id='E016',
|
id='fields.E304',
|
||||||
),
|
),
|
||||||
Error(
|
Error(
|
||||||
'Clash between accessors for Model.second_m2m and Model.first_m2m.',
|
"Reverse accessor for 'Model.second_m2m' clashes with reverse accessor for 'Model.first_m2m'.",
|
||||||
hint=('Add or change a related_name argument to the definition '
|
hint=("Add or change a related_name argument to the definition "
|
||||||
'for Model.second_m2m or Model.first_m2m.'),
|
"for 'Model.second_m2m' or 'Model.first_m2m'."),
|
||||||
obj=Model._meta.get_field('second_m2m'),
|
obj=Model._meta.get_field('second_m2m'),
|
||||||
id='E016',
|
id='fields.E304',
|
||||||
),
|
),
|
||||||
]
|
]
|
||||||
self.assertEqual(errors, expected)
|
self.assertEqual(errors, expected)
|
||||||
|
@ -827,12 +814,12 @@ class SelfReferentialM2MClashTests(IsolatedModelsTestCase):
|
||||||
errors = Model.check()
|
errors = Model.check()
|
||||||
expected = [
|
expected = [
|
||||||
Error(
|
Error(
|
||||||
'Accessor for field Model.model_set clashes with field Model.model_set.',
|
"Reverse accessor for 'Model.model_set' clashes with field name 'Model.model_set'.",
|
||||||
hint=('Rename field Model.model_set or add/change '
|
hint=("Rename field 'Model.model_set', or add/change "
|
||||||
'a related_name argument to the definition '
|
"a related_name argument to the definition "
|
||||||
'for field Model.model_set.'),
|
"for field 'Model.model_set'."),
|
||||||
obj=Model._meta.get_field('model_set'),
|
obj=Model._meta.get_field('model_set'),
|
||||||
id='E014',
|
id='fields.E302',
|
||||||
),
|
),
|
||||||
]
|
]
|
||||||
self.assertEqual(errors, expected)
|
self.assertEqual(errors, expected)
|
||||||
|
@ -844,11 +831,11 @@ class SelfReferentialM2MClashTests(IsolatedModelsTestCase):
|
||||||
errors = Model.check()
|
errors = Model.check()
|
||||||
expected = [
|
expected = [
|
||||||
Error(
|
Error(
|
||||||
'Reverse query name for field Model.model clashes with field Model.model.',
|
"Reverse query name for 'Model.model' clashes with field name 'Model.model'.",
|
||||||
hint=('Rename field Model.model or add/change a related_name '
|
hint=("Rename field 'Model.model', or add/change a related_name "
|
||||||
'argument to the definition for field Model.model.'),
|
"argument to the definition for field 'Model.model'."),
|
||||||
obj=Model._meta.get_field('model'),
|
obj=Model._meta.get_field('model'),
|
||||||
id='E015',
|
id='fields.E303',
|
||||||
),
|
),
|
||||||
]
|
]
|
||||||
self.assertEqual(errors, expected)
|
self.assertEqual(errors, expected)
|
||||||
|
@ -862,18 +849,18 @@ class SelfReferentialM2MClashTests(IsolatedModelsTestCase):
|
||||||
errors = Model.check()
|
errors = Model.check()
|
||||||
expected = [
|
expected = [
|
||||||
Error(
|
Error(
|
||||||
'Accessor for field Model.m2m clashes with field Model.clash.',
|
"Reverse accessor for 'Model.m2m' clashes with field name 'Model.clash'.",
|
||||||
hint=('Rename field Model.clash or add/change a related_name '
|
hint=("Rename field 'Model.clash', or add/change a related_name "
|
||||||
'argument to the definition for field Model.m2m.'),
|
"argument to the definition for field 'Model.m2m'."),
|
||||||
obj=Model._meta.get_field('m2m'),
|
obj=Model._meta.get_field('m2m'),
|
||||||
id='E014',
|
id='fields.E302',
|
||||||
),
|
),
|
||||||
Error(
|
Error(
|
||||||
'Reverse query name for field Model.m2m clashes with field Model.clash.',
|
"Reverse query name for 'Model.m2m' clashes with field name 'Model.clash'.",
|
||||||
hint=('Rename field Model.clash or add/change a related_name '
|
hint=("Rename field 'Model.clash', or add/change a related_name "
|
||||||
'argument to the definition for field Model.m2m.'),
|
"argument to the definition for field 'Model.m2m'."),
|
||||||
obj=Model._meta.get_field('m2m'),
|
obj=Model._meta.get_field('m2m'),
|
||||||
id='E015',
|
id='fields.E303',
|
||||||
),
|
),
|
||||||
]
|
]
|
||||||
self.assertEqual(errors, expected)
|
self.assertEqual(errors, expected)
|
||||||
|
@ -898,12 +885,12 @@ class SelfReferentialFKClashTests(IsolatedModelsTestCase):
|
||||||
errors = Model.check()
|
errors = Model.check()
|
||||||
expected = [
|
expected = [
|
||||||
Error(
|
Error(
|
||||||
'Accessor for field Model.model_set clashes with field Model.model_set.',
|
"Reverse accessor for 'Model.model_set' clashes with field name 'Model.model_set'.",
|
||||||
hint=('Rename field Model.model_set or add/change '
|
hint=("Rename field 'Model.model_set', or add/change "
|
||||||
'a related_name argument to the definition '
|
"a related_name argument to the definition "
|
||||||
'for field Model.model_set.'),
|
"for field 'Model.model_set'."),
|
||||||
obj=Model._meta.get_field('model_set'),
|
obj=Model._meta.get_field('model_set'),
|
||||||
id='E014',
|
id='fields.E302',
|
||||||
),
|
),
|
||||||
]
|
]
|
||||||
self.assertEqual(errors, expected)
|
self.assertEqual(errors, expected)
|
||||||
|
@ -915,12 +902,12 @@ class SelfReferentialFKClashTests(IsolatedModelsTestCase):
|
||||||
errors = Model.check()
|
errors = Model.check()
|
||||||
expected = [
|
expected = [
|
||||||
Error(
|
Error(
|
||||||
'Reverse query name for field Model.model clashes with field Model.model.',
|
"Reverse query name for 'Model.model' clashes with field name 'Model.model'.",
|
||||||
hint=('Rename field Model.model or add/change '
|
hint=("Rename field 'Model.model', or add/change "
|
||||||
'a related_name argument to the definition '
|
"a related_name argument to the definition "
|
||||||
'for field Model.model.'),
|
"for field 'Model.model'."),
|
||||||
obj=Model._meta.get_field('model'),
|
obj=Model._meta.get_field('model'),
|
||||||
id='E015',
|
id='fields.E303',
|
||||||
),
|
),
|
||||||
]
|
]
|
||||||
self.assertEqual(errors, expected)
|
self.assertEqual(errors, expected)
|
||||||
|
@ -933,20 +920,20 @@ class SelfReferentialFKClashTests(IsolatedModelsTestCase):
|
||||||
errors = Model.check()
|
errors = Model.check()
|
||||||
expected = [
|
expected = [
|
||||||
Error(
|
Error(
|
||||||
'Accessor for field Model.foreign clashes with field Model.clash.',
|
"Reverse accessor for 'Model.foreign' clashes with field name 'Model.clash'.",
|
||||||
hint=('Rename field Model.clash or add/change '
|
hint=("Rename field 'Model.clash', or add/change "
|
||||||
'a related_name argument to the definition '
|
"a related_name argument to the definition "
|
||||||
'for field Model.foreign.'),
|
"for field 'Model.foreign'."),
|
||||||
obj=Model._meta.get_field('foreign'),
|
obj=Model._meta.get_field('foreign'),
|
||||||
id='E014',
|
id='fields.E302',
|
||||||
),
|
),
|
||||||
Error(
|
Error(
|
||||||
'Reverse query name for field Model.foreign clashes with field Model.clash.',
|
"Reverse query name for 'Model.foreign' clashes with field name 'Model.clash'.",
|
||||||
hint=('Rename field Model.clash or add/change '
|
hint=("Rename field 'Model.clash', or add/change "
|
||||||
'a related_name argument to the definition '
|
"a related_name argument to the definition "
|
||||||
'for field Model.foreign.'),
|
"for field 'Model.foreign'."),
|
||||||
obj=Model._meta.get_field('foreign'),
|
obj=Model._meta.get_field('foreign'),
|
||||||
id='E015',
|
id='fields.E303',
|
||||||
),
|
),
|
||||||
]
|
]
|
||||||
self.assertEqual(errors, expected)
|
self.assertEqual(errors, expected)
|
||||||
|
@ -976,91 +963,91 @@ class ComplexClashTests(IsolatedModelsTestCase):
|
||||||
errors = Model.check()
|
errors = Model.check()
|
||||||
expected = [
|
expected = [
|
||||||
Error(
|
Error(
|
||||||
'Accessor for field Model.foreign_1 clashes with field Target.id.',
|
"Reverse accessor for 'Model.foreign_1' clashes with field name 'Target.id'.",
|
||||||
hint=('Rename field Target.id or add/change a related_name '
|
hint=("Rename field 'Target.id', or add/change a related_name "
|
||||||
'argument to the definition for field Model.foreign_1.'),
|
"argument to the definition for field 'Model.foreign_1'."),
|
||||||
obj=Model._meta.get_field('foreign_1'),
|
obj=Model._meta.get_field('foreign_1'),
|
||||||
id='E014',
|
id='fields.E302',
|
||||||
),
|
),
|
||||||
Error(
|
Error(
|
||||||
'Reverse query name for field Model.foreign_1 clashes with field Target.id.',
|
"Reverse query name for 'Model.foreign_1' clashes with field name 'Target.id'.",
|
||||||
hint=('Rename field Target.id or add/change a related_name '
|
hint=("Rename field 'Target.id', or add/change a related_name "
|
||||||
'argument to the definition for field Model.foreign_1.'),
|
"argument to the definition for field 'Model.foreign_1'."),
|
||||||
obj=Model._meta.get_field('foreign_1'),
|
obj=Model._meta.get_field('foreign_1'),
|
||||||
id='E015',
|
id='fields.E303',
|
||||||
),
|
),
|
||||||
Error(
|
Error(
|
||||||
'Clash between accessors for Model.foreign_1 and Model.m2m_1.',
|
"Reverse accessor for 'Model.foreign_1' clashes with reverse accessor for 'Model.m2m_1'.",
|
||||||
hint=('Add or change a related_name argument to '
|
hint=("Add or change a related_name argument to "
|
||||||
'the definition for Model.foreign_1 or Model.m2m_1.'),
|
"the definition for 'Model.foreign_1' or 'Model.m2m_1'."),
|
||||||
obj=Model._meta.get_field('foreign_1'),
|
obj=Model._meta.get_field('foreign_1'),
|
||||||
id='E016',
|
id='fields.E304',
|
||||||
),
|
),
|
||||||
Error(
|
Error(
|
||||||
'Clash between reverse query names for Model.foreign_1 and Model.m2m_1.',
|
"Reverse query name for 'Model.foreign_1' clashes with reverse query name for 'Model.m2m_1'.",
|
||||||
hint=('Add or change a related_name argument to '
|
hint=("Add or change a related_name argument to "
|
||||||
'the definition for Model.foreign_1 or Model.m2m_1.'),
|
"the definition for 'Model.foreign_1' or 'Model.m2m_1'."),
|
||||||
obj=Model._meta.get_field('foreign_1'),
|
obj=Model._meta.get_field('foreign_1'),
|
||||||
id='E017',
|
id='fields.E305',
|
||||||
),
|
),
|
||||||
|
|
||||||
Error(
|
Error(
|
||||||
'Clash between accessors for Model.foreign_2 and Model.m2m_2.',
|
"Reverse accessor for 'Model.foreign_2' clashes with reverse accessor for 'Model.m2m_2'.",
|
||||||
hint=('Add or change a related_name argument '
|
hint=("Add or change a related_name argument "
|
||||||
'to the definition for Model.foreign_2 or Model.m2m_2.'),
|
"to the definition for 'Model.foreign_2' or 'Model.m2m_2'."),
|
||||||
obj=Model._meta.get_field('foreign_2'),
|
obj=Model._meta.get_field('foreign_2'),
|
||||||
id='E016',
|
id='fields.E304',
|
||||||
),
|
),
|
||||||
Error(
|
Error(
|
||||||
'Clash between reverse query names for Model.foreign_2 and Model.m2m_2.',
|
"Reverse query name for 'Model.foreign_2' clashes with reverse query name for 'Model.m2m_2'.",
|
||||||
hint=('Add or change a related_name argument to '
|
hint=("Add or change a related_name argument to "
|
||||||
'the definition for Model.foreign_2 or Model.m2m_2.'),
|
"the definition for 'Model.foreign_2' or 'Model.m2m_2'."),
|
||||||
obj=Model._meta.get_field('foreign_2'),
|
obj=Model._meta.get_field('foreign_2'),
|
||||||
id='E017',
|
id='fields.E305',
|
||||||
),
|
),
|
||||||
|
|
||||||
Error(
|
Error(
|
||||||
'Accessor for field Model.m2m_1 clashes with field Target.id.',
|
"Reverse accessor for 'Model.m2m_1' clashes with field name 'Target.id'.",
|
||||||
hint=('Rename field Target.id or add/change a related_name '
|
hint=("Rename field 'Target.id', or add/change a related_name "
|
||||||
'argument to the definition for field Model.m2m_1.'),
|
"argument to the definition for field 'Model.m2m_1'."),
|
||||||
obj=Model._meta.get_field('m2m_1'),
|
obj=Model._meta.get_field('m2m_1'),
|
||||||
id='E014',
|
id='fields.E302',
|
||||||
),
|
),
|
||||||
Error(
|
Error(
|
||||||
'Reverse query name for field Model.m2m_1 clashes with field Target.id.',
|
"Reverse query name for 'Model.m2m_1' clashes with field name 'Target.id'.",
|
||||||
hint=('Rename field Target.id or add/change a related_name '
|
hint=("Rename field 'Target.id', or add/change a related_name "
|
||||||
'argument to the definition for field Model.m2m_1.'),
|
"argument to the definition for field 'Model.m2m_1'."),
|
||||||
obj=Model._meta.get_field('m2m_1'),
|
obj=Model._meta.get_field('m2m_1'),
|
||||||
id='E015',
|
id='fields.E303',
|
||||||
),
|
),
|
||||||
Error(
|
Error(
|
||||||
'Clash between accessors for Model.m2m_1 and Model.foreign_1.',
|
"Reverse accessor for 'Model.m2m_1' clashes with reverse accessor for 'Model.foreign_1'.",
|
||||||
hint=('Add or change a related_name argument to the definition '
|
hint=("Add or change a related_name argument to the definition "
|
||||||
'for Model.m2m_1 or Model.foreign_1.'),
|
"for 'Model.m2m_1' or 'Model.foreign_1'."),
|
||||||
obj=Model._meta.get_field('m2m_1'),
|
obj=Model._meta.get_field('m2m_1'),
|
||||||
id='E016',
|
id='fields.E304',
|
||||||
),
|
),
|
||||||
Error(
|
Error(
|
||||||
'Clash between reverse query names for Model.m2m_1 and Model.foreign_1.',
|
"Reverse query name for 'Model.m2m_1' clashes with reverse query name for 'Model.foreign_1'.",
|
||||||
hint=('Add or change a related_name argument to '
|
hint=("Add or change a related_name argument to "
|
||||||
'the definition for Model.m2m_1 or Model.foreign_1.'),
|
"the definition for 'Model.m2m_1' or 'Model.foreign_1'."),
|
||||||
obj=Model._meta.get_field('m2m_1'),
|
obj=Model._meta.get_field('m2m_1'),
|
||||||
id='E017',
|
id='fields.E305',
|
||||||
),
|
),
|
||||||
|
|
||||||
Error(
|
Error(
|
||||||
'Clash between accessors for Model.m2m_2 and Model.foreign_2.',
|
"Reverse accessor for 'Model.m2m_2' clashes with reverse accessor for 'Model.foreign_2'.",
|
||||||
hint=('Add or change a related_name argument to the definition '
|
hint=("Add or change a related_name argument to the definition "
|
||||||
'for Model.m2m_2 or Model.foreign_2.'),
|
"for 'Model.m2m_2' or 'Model.foreign_2'."),
|
||||||
obj=Model._meta.get_field('m2m_2'),
|
obj=Model._meta.get_field('m2m_2'),
|
||||||
id='E016',
|
id='fields.E304',
|
||||||
),
|
),
|
||||||
Error(
|
Error(
|
||||||
'Clash between reverse query names for Model.m2m_2 and Model.foreign_2.',
|
"Reverse query name for 'Model.m2m_2' clashes with reverse query name for 'Model.foreign_2'.",
|
||||||
hint=('Add or change a related_name argument to the definition '
|
hint=("Add or change a related_name argument to the definition "
|
||||||
'for Model.m2m_2 or Model.foreign_2.'),
|
"for 'Model.m2m_2' or 'Model.foreign_2'."),
|
||||||
obj=Model._meta.get_field('m2m_2'),
|
obj=Model._meta.get_field('m2m_2'),
|
||||||
id='E017',
|
id='fields.E305',
|
||||||
),
|
),
|
||||||
]
|
]
|
||||||
self.assertEqual(errors, expected)
|
self.assertEqual(errors, expected)
|
||||||
|
|
|
@ -37,7 +37,7 @@ class ModelValidationTest(TestCase):
|
||||||
"sender, which has not been installed.",
|
"sender, which has not been installed.",
|
||||||
hint=None,
|
hint=None,
|
||||||
obj='model_validation.tests',
|
obj='model_validation.tests',
|
||||||
id='E014',
|
id='signals.E001',
|
||||||
),
|
),
|
||||||
Error(
|
Error(
|
||||||
"An instance of the `OnPostInit` class was connected to "
|
"An instance of the `OnPostInit` class was connected to "
|
||||||
|
@ -45,7 +45,7 @@ class ModelValidationTest(TestCase):
|
||||||
"'missing-app.Model' sender, which has not been installed.",
|
"'missing-app.Model' sender, which has not been installed.",
|
||||||
hint=None,
|
hint=None,
|
||||||
obj='model_validation.tests',
|
obj='model_validation.tests',
|
||||||
id='E014',
|
id='signals.E001',
|
||||||
)
|
)
|
||||||
]
|
]
|
||||||
self.assertEqual(errors, expected)
|
self.assertEqual(errors, expected)
|
||||||
|
|
Loading…
Reference in New Issue