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