def test_many_to_many_with_useless_options(self): class Model(models.Model): name = models.CharField(max_length=20) class ModelM2M(models.Model): m2m = models.ManyToManyField(Model, null=True, validators=['']) errors = ModelM2M.check() field = ModelM2M._meta.get_field('m2m') expected = [ DjangoWarning( 'null has no effect on ManyToManyField.', hint=None, obj=field, id='fields.W340', ) ] expected.append( DjangoWarning( 'ManyToManyField does not support validators.', hint=None, obj=field, id='fields.W341', )) self.assertEqual(errors, expected)
def test_fix_default_value(self): class Model(models.Model): field_dt = models.TimeField(default=now()) field_t = models.TimeField(default=now().time()) field_now = models.DateField(default=now) field_dt = Model._meta.get_field('field_dt') field_t = Model._meta.get_field('field_t') field_now = Model._meta.get_field('field_now') errors = field_dt.check() errors.extend(field_t.check()) errors.extend(field_now.check()) # doesn't raise a warning self.assertEqual(errors, [ DjangoWarning( 'Fixed default value provided.', hint='It seems you set a fixed date / time / datetime ' 'value as default for this field. This may not be ' 'what you want. If you want to have the current date ' 'as default, use `django.utils.timezone.now`', obj=field_dt, id='fields.W161', ), DjangoWarning( 'Fixed default value provided.', hint='It seems you set a fixed date / time / datetime ' 'value as default for this field. This may not be ' 'what you want. If you want to have the current date ' 'as default, use `django.utils.timezone.now`', obj=field_t, id='fields.W161', ) ])
def test_fix_default_value(self): class Model(models.Model): field_dt = models.TimeField(default=now()) field_t = models.TimeField(default=now().time()) # Timezone-aware time object (when USE_TZ=True). field_tz = models.TimeField(default=now().timetz()) field_now = models.DateField(default=now) names = ["field_dt", "field_t", "field_tz", "field_now"] fields = [Model._meta.get_field(name) for name in names] errors = [] for field in fields: errors.extend(field.check()) self.assertEqual( errors, [ DjangoWarning( "Fixed default value provided.", hint="It seems you set a fixed date / time / datetime " "value as default for this field. This may not be " "what you want. If you want to have the current date " "as default, use `django.utils.timezone.now`", obj=fields[0], id="fields.W161", ), DjangoWarning( "Fixed default value provided.", hint="It seems you set a fixed date / time / datetime " "value as default for this field. This may not be " "what you want. If you want to have the current date " "as default, use `django.utils.timezone.now`", obj=fields[1], id="fields.W161", ), DjangoWarning( "Fixed default value provided.", hint=( "It seems you set a fixed date / time / datetime value as " "default for this field. This may not be what you want. " "If you want to have the current date as default, use " "`django.utils.timezone.now`" ), obj=fields[2], id="fields.W161", ), # field_now doesn't raise a warning. ], )
def test_max_length_warning(self): class Model(models.Model): integer = models.IntegerField(max_length=2) biginteger = models.BigIntegerField(max_length=2) smallinteger = models.SmallIntegerField(max_length=2) positiveinteger = models.PositiveIntegerField(max_length=2) positivebiginteger = models.PositiveBigIntegerField(max_length=2) positivesmallinteger = models.PositiveSmallIntegerField(max_length=2) for field in Model._meta.get_fields(): if field.auto_created: continue with self.subTest(name=field.name): self.assertEqual( field.check(), [ DjangoWarning( "'max_length' is ignored when used with %s." % field.__class__.__name__, hint="Remove 'max_length' from field", obj=field, id="fields.W122", ) ], )
def test_fix_default_value(self): class Model(models.Model): field_dt = models.TimeField(default=now()) field_t = models.TimeField(default=now().time()) # Timezone-aware time object (when USE_TZ=True). field_tz = models.TimeField(default=now().timetz()) field_now = models.DateField(default=now) names = ['field_dt', 'field_t', 'field_tz', 'field_now'] fields = [Model._meta.get_field(name) for name in names] errors = [] for field in fields: errors.extend(field.check()) self.assertEqual( errors, [ DjangoWarning( 'Fixed default value provided.', hint='It seems you set a fixed date / time / datetime ' 'value as default for this field. This may not be ' 'what you want. If you want to have the current date ' 'as default, use `django.utils.timezone.now`', obj=fields[0], id='fields.W161', ), DjangoWarning( 'Fixed default value provided.', hint='It seems you set a fixed date / time / datetime ' 'value as default for this field. This may not be ' 'what you want. If you want to have the current date ' 'as default, use `django.utils.timezone.now`', obj=fields[1], id='fields.W161', ), DjangoWarning( 'Fixed default value provided.', hint= ('It seems you set a fixed date / time / datetime value as ' 'default for this field. This may not be what you want. ' 'If you want to have the current date as default, use ' '`django.utils.timezone.now`'), obj=fields[2], id='fields.W161', ), # field_now doesn't raise a warning. ])
def test_model_field_deprecation_message(self): self.assertEqual( JSONModel().check(), [ DjangoWarning( "You are using Django 3.1 or newer, which already has a built-in JSONField.", hint="Use django.db.models.JSONField instead.", obj=JSONModel._meta.get_field("value"), id="django_jsonfield_backport.W001", ), ], )
def test_max_length_warning(self): class Model(models.Model): value = models.IntegerField(max_length=2) field = Model._meta.get_field('value') self.assertEqual(field.check(), [ DjangoWarning( "'max_length' is ignored when used with IntegerField", hint="Remove 'max_length' from field", obj=field, id='fields.W122', ) ])
def test_max_length_warning(self): class Model(models.Model): auto = models.AutoField(primary_key=True, max_length=2) field = Model._meta.get_field('auto') self.assertEqual(field.check(), [ DjangoWarning( "'max_length' is ignored when used with %s." % field.__class__.__name__, hint="Remove 'max_length' from field", obj=field, id='fields.W122', ), ])
def test_model_field_deprecation_message(self): class PostgreSQLJSONModel(PostgreSQLModel): field = JSONField() self.assertEqual(PostgreSQLJSONModel().check(), [ DjangoWarning( 'django.contrib.postgres.fields.JSONField is deprecated. ' 'Support for it (except in historical migrations) will be ' 'removed in Django 4.0.', hint='Use django.db.models.JSONField instead.', obj=PostgreSQLJSONModel._meta.get_field('field'), id='fields.W904', ), ])
def test_max_length_warning(self): class Model(models.Model): value = models.IntegerField(max_length=2) value = Model._meta.get_field('value') errors = Model.check() expected = [ DjangoWarning( "'max_length' is ignored when used with IntegerField", hint="Remove 'max_length' from field", obj=value, id='fields.W122', ) ] self.assertEqual(errors, expected)
def test_max_length_warning(self): class Model(models.Model): value = models.TextField(db_index=True) field = Model._meta.get_field('value') field_type = field.db_type(connection) self.assertEqual(field.check(), [ DjangoWarning( '%s does not support a database index on %s columns.' % (connection.display_name, field_type), hint=("An index won't be created. Silence this warning if you " "don't care about it."), obj=field, id='fields.W162', ) ])
def test_invalid_default(self): class InvalidDefaultModel(models.Model): field = JSONField(default={}) self.assertEqual( InvalidDefaultModel._meta.get_field("field").check(), [ DjangoWarning( msg= ("JSONField default should be a callable instead of an instance " "so that it's not shared between all field instances."), hint= "Use a callable instead, e.g., use `dict` instead of `{}`.", obj=InvalidDefaultModel._meta.get_field("field"), id="fields.E010", ) ], )
def test_invalid_default(self): class Model(models.Model): field = models.JSONField(default={}) self.assertEqual( Model._meta.get_field('field').check(), [ DjangoWarning( msg=( "JSONField default should be a callable instead of an " "instance so that it's not shared between all field " "instances."), hint= ('Use a callable instead, e.g., use `dict` instead of `{}`.' ), obj=Model._meta.get_field('field'), id='fields.E010', ) ])
def test_too_long_char_field_under_mysql(self): from django.db.backends.mysql.validation import DatabaseValidation class Model(models.Model): field = models.CharField(unique=True, max_length=256) field = Model._meta.get_field('field') validator = DatabaseValidation(connection=connection) self.assertEqual(validator.check_field(field), [ DjangoWarning( '%s may not allow unique CharFields to have a max_length > ' '255.' % connection.display_name, hint=( 'See: https://docs.djangoproject.com/en/%s/ref/databases/' '#mysql-character-fields' % get_docs_version()), obj=field, id='mysql.W003', ) ])