def test_multiinheritance_clash(self): class Mother(models.Model): clash = models.IntegerField() class Father(models.Model): clash = models.IntegerField() class Child(Mother, Father): # Here we have two clashed: id (automatic field) and clash, because # both parents define these fields. pass self.assertEqual(Child.check(), [ Error( "The field 'id' from parent model " "'invalid_models_tests.mother' clashes with the field 'id' " "from parent model 'invalid_models_tests.father'.", obj=Child, id='models.E005', ), Error( "The field 'clash' from parent model " "'invalid_models_tests.mother' clashes with the field 'clash' " "from parent model 'invalid_models_tests.father'.", obj=Child, id='models.E005', ) ])
def test_local_field_long_column_name(self): """ #13711 -- Model check for long column names when database does not support long names. """ allowed_len, db_alias = get_max_column_name_length() class ModelWithLongField(models.Model): title = models.CharField(max_length=11) long_field_name = 'a' * (self.max_column_name_length + 1) long_field_name2 = 'b' * (self.max_column_name_length + 1) models.CharField(max_length=11).contribute_to_class( ModelWithLongField, long_field_name) models.CharField(max_length=11, db_column='vlmn').contribute_to_class( ModelWithLongField, long_field_name2) self.assertEqual(ModelWithLongField.check(), [ Error( 'Autogenerated column name too long for field "%s". ' 'Maximum length is "%s" for database "%s".' % (long_field_name, self.max_column_name_length, self.column_limit_db_alias), hint="Set the column name manually using 'db_column'.", obj=ModelWithLongField, id='models.E018', ) ])
def test_multiple_inheritance_cannot_shadow_concrete_inherited_field(self): class ConcreteParent(models.Model): name = models.CharField(max_length=255) class AbstractParent(models.Model): name = models.IntegerField() class Meta: abstract = True class FirstChild(ConcreteParent, AbstractParent): pass class AnotherChild(AbstractParent, ConcreteParent): pass self.assertIsInstance(FirstChild._meta.get_field('name'), models.CharField) self.assertEqual( AnotherChild.check(), [Error( "The field 'name' clashes with the field 'name' " "from model 'model_inheritance.concreteparent'.", obj=AnotherChild._meta.get_field('name'), id="models.E006", )] )
def test_auto_now_and_auto_now_add_raise_error(self): class Model(models.Model): field0 = models.DateTimeField(auto_now=True, auto_now_add=True, default=now) field1 = models.DateTimeField(auto_now=True, auto_now_add=False, default=now) field2 = models.DateTimeField(auto_now=False, auto_now_add=True, default=now) field3 = models.DateTimeField(auto_now=True, auto_now_add=True, default=None) expected = [] checks = [] for i in range(4): field = Model._meta.get_field('field%d' % i) expected.append( Error( "The options auto_now, auto_now_add, and default " "are mutually exclusive. Only one of these options " "may be present.", obj=field, id='fields.E160', )) checks.extend(field.check()) self.assertEqual(checks, expected)
def test_multi_inheritance_field_clashes(self): class AbstractBase(models.Model): name = models.CharField(max_length=30) class Meta: abstract = True class ConcreteBase(AbstractBase): pass class AbstractDescendant(ConcreteBase): class Meta: abstract = True class ConcreteDescendant(AbstractDescendant): name = models.CharField(max_length=100) self.assertEqual( ConcreteDescendant.check(), [Error( "The field 'name' clashes with the field 'name' from " "model 'model_inheritance.concretebase'.", obj=ConcreteDescendant._meta.get_field('name'), id="models.E006", )] )
def test_bad_values_of_max_digits_and_decimal_places(self): class Model(models.Model): field = models.DecimalField(max_digits="bad", decimal_places="bad") field = Model._meta.get_field('field') self.assertEqual(field.check(), [ Error( "'decimal_places' must be a non-negative integer.", obj=field, id='fields.E131', ), Error( "'max_digits' must be a positive integer.", obj=field, id='fields.E133', ), ])
def test_required_attributes(self): class Model(models.Model): field = models.DecimalField() field = Model._meta.get_field('field') self.assertEqual(field.check(), [ Error( "DecimalFields must define a 'decimal_places' attribute.", obj=field, id='fields.E130', ), Error( "DecimalFields must define a 'max_digits' attribute.", obj=field, id='fields.E132', ), ])
def default_error(model_key, func, args, keywords): error_msg = "%(op)s contains a lazy reference to %(model)s, but %(model_error)s." params = { 'op': func, 'model': '.'.join(model_key), 'model_error': app_model_error(model_key), } return Error(error_msg % params, obj=func, id='models.E022')
def test_ending_with_underscore(self): class Model(models.Model): field_ = models.CharField(max_length=10) m2m_ = models.ManyToManyField('self') self.assertEqual(Model.check(), [ Error( 'Field names must not end with an underscore.', obj=Model._meta.get_field('field_'), id='fields.E001', ), Error( 'Field names must not end with an underscore.', obj=Model._meta.get_field('m2m_'), id='fields.E001', ), ])
def test_check_field(self): """ Test if backend specific checks are performed. """ error = Error('an error') class Model(models.Model): field = models.IntegerField() field = Model._meta.get_field('field') with mock.patch.object(connections['default'].validation, 'check_field', return_value=[error]): self.assertEqual(field.check(), [error])
def test_str_max_length_type(self): class Model(models.Model): field = models.CharField(max_length=True) field = Model._meta.get_field('field') self.assertEqual(field.check(), [ Error("'max_length' must be a positive integer.", obj=field, id='fields.E121'), ])
def field_error(model_key, func, args, keywords): error_msg = ( "The field %(field)s was declared with a lazy reference " "to '%(model)s', but %(model_error)s." ) params = { 'model': '.'.join(model_key), 'field': keywords['field'], 'model_error': app_model_error(model_key), } return Error(error_msg % params, obj=keywords['field'], id='fields.E307')
def test_pk(self): class Model(models.Model): pk = models.IntegerField() self.assertEqual(Model.check(), [ Error( "'pk' is a reserved word that cannot be used as a field name.", obj=Model._meta.get_field('pk'), id='fields.E003', ) ])
def test_swappable_missing_app_name(self): class Model(models.Model): class Meta: swappable = 'TEST_SWAPPED_MODEL_BAD_VALUE' self.assertEqual(Model.check(), [ Error( "'TEST_SWAPPED_MODEL_BAD_VALUE' is not of the form 'app_label.app_name'.", id='models.E001', ), ])
def test_including_separator(self): class Model(models.Model): some__field = models.IntegerField() self.assertEqual(Model.check(), [ Error( 'Field names must not contain "__".', obj=Model._meta.get_field('some__field'), id='fields.E002', ) ])
def test_swappable_missing_app(self): class Model(models.Model): class Meta: swappable = 'TEST_SWAPPED_MODEL_BAD_MODEL' self.assertEqual(Model.check(), [ Error( "'TEST_SWAPPED_MODEL_BAD_MODEL' references 'not_an_app.Target', " 'which has not been installed, or is abstract.', id='models.E002', ), ])
def test_single_primary_key(self): class Model(models.Model): foo = models.IntegerField(primary_key=True) bar = models.IntegerField(primary_key=True) self.assertEqual(Model.check(), [ Error( "The model cannot have more than one field with 'primary_key=True'.", obj=Model, id='models.E026', ) ])
def test_name_contains_double_underscores(self): class Test__Model(models.Model): pass self.assertEqual(Test__Model.check(), [ Error( "The model name 'Test__Model' cannot contain double underscores " "as it collides with the query lookup syntax.", obj=Test__Model, id='models.E024', ) ])
def test_name_ending_with_underscore(self): class Model_(models.Model): pass self.assertEqual(Model_.check(), [ Error( "The model name 'Model_' cannot start or end with an underscore " "as it collides with the query lookup syntax.", obj=Model_, id='models.E023', ) ])
def test_pointing_to_missing_field(self): class Model(models.Model): class Meta: index_together = [['missing_field']] self.assertEqual(Model.check(), [ Error( "'index_together' refers to the nonexistent field 'missing_field'.", obj=Model, id='models.E012', ), ])
def test_non_iterable(self): class Model(models.Model): class Meta: unique_together = 42 self.assertEqual(Model.check(), [ Error( "'unique_together' must be a list or tuple.", obj=Model, id='models.E010', ), ])
def test_ordering_pointing_to_missing_field(self): class Model(models.Model): class Meta: ordering = ('missing_field', ) self.assertEqual(Model.check(), [ Error( "'ordering' refers to the nonexistent field 'missing_field'.", obj=Model, id='models.E015', ) ])
def test_list_containing_non_iterable(self): class Model(models.Model): class Meta: index_together = [('a', 'b'), 42] self.assertEqual(Model.check(), [ Error( "All 'index_together' elements must be lists or tuples.", obj=Model, id='models.E009', ), ])
def test_decimal_places_greater_than_max_digits(self): class Model(models.Model): field = models.DecimalField(max_digits=9, decimal_places=10) field = Model._meta.get_field('field') self.assertEqual(field.check(), [ Error( "'max_digits' must be greater or equal to 'decimal_places'.", obj=field, id='fields.E134', ), ])
def test_non_list(self): class Model(models.Model): class Meta: index_together = 'not-a-list' self.assertEqual(Model.check(), [ Error( "'index_together' must be a list or tuple.", obj=Model, id='models.E008', ), ])
def test_primary_key(self): class Model(models.Model): field = models.FileField(primary_key=False, upload_to='somewhere') field = Model._meta.get_field('field') self.assertEqual(field.check(), [ Error( "'primary_key' is not a valid argument for a FileField.", obj=field, id='fields.E201', ) ])
def test_missing_max_length(self): class Model(models.Model): field = models.CharField() field = Model._meta.get_field('field') self.assertEqual(field.check(), [ Error( "CharFields must define a 'max_length' attribute.", obj=field, id='fields.E120', ), ])
def test_bad_db_index_value(self): class Model(models.Model): field = models.CharField(max_length=10, db_index='bad') field = Model._meta.get_field('field') self.assertEqual(field.check(), [ Error( "'db_index' must be None, True or False.", obj=field, id='fields.E006', ), ])
def test_name_beginning_with_underscore(self): class _Model(models.Model): pass self.assertEqual(_Model.check(), [ Error( "The model name '_Model' cannot start or end with an underscore " "as it collides with the query lookup syntax.", obj=_Model, id='models.E023', ) ])
def test_pointing_to_missing_field(self): class Model(models.Model): class Meta: indexes = [models.Index(fields=['missing_field'], name='name')] self.assertEqual(Model.check(), [ Error( "'indexes' refers to the nonexistent field 'missing_field'.", obj=Model, id='models.E012', ), ])