Commit 71ebcb85 authored by Simon Charette's avatar Simon Charette
Browse files

Fixed #25417 -- Added a field check for invalid default values.

parent 75ed5900
Loading
Loading
Loading
Loading
+17 −0
Original line number Diff line number Diff line
@@ -207,6 +207,7 @@ class Field(RegisterLookupMixin):
        errors = []
        errors.extend(self._check_field_name())
        errors.extend(self._check_choices())
        errors.extend(self._check_default())
        errors.extend(self._check_db_index())
        errors.extend(self._check_null_allowed_for_primary_keys())
        errors.extend(self._check_backend_specific_checks(**kwargs))
@@ -283,6 +284,22 @@ class Field(RegisterLookupMixin):
        else:
            return []

    def _check_default(self):
        if self.has_default():
            default = self.get_default()
            try:
                self.clean(default, None)
            except exceptions.ValidationError as messages:
                return [
                    checks.Error(
                        "Invalid 'default' value: %s" % message,
                        hint=None,
                        obj=self,
                        id='fields.E008',
                    ) for message in messages
                ]
        return []

    def _check_db_index(self):
        if self.db_index not in (None, True, False):
            return [
+1 −0
Original line number Diff line number Diff line
@@ -140,6 +140,7 @@ Fields
  human readable name)`` tuples.
* **fields.E006**: ``db_index`` must be ``None``, ``True`` or ``False``.
* **fields.E007**: Primary keys must not have ``null=True``.
* **fields.E008**: Invalid ``default`` value.
* **fields.E100**: ``AutoField``\s must set primary_key=True.
* **fields.E110**: ``BooleanField``\s do not accept null values.
* **fields.E120**: ``CharField``\s must define a ``max_length`` attribute.
+3 −0
Original line number Diff line number Diff line
@@ -512,6 +512,9 @@ Models

* ``connection.queries`` shows queries with substituted parameters on SQLite.

* Added a new model field check that makes sure
  :attr:`~django.db.models.Field.default` is a valid value.

CSRF
^^^^

+68 −0
Original line number Diff line number Diff line
# -*- encoding: utf-8 -*-
from __future__ import unicode_literals

import decimal
import unittest

from django.core.checks import Error, Warning as DjangoWarning
@@ -64,6 +65,22 @@ class BooleanFieldTests(IsolatedModelsTestCase):
        ]
        self.assertEqual(errors, expected)

    def test_invalid_default(self):
        class Model(models.Model):
            field = models.BooleanField(default='invalid')

        field = Model._meta.get_field('field')
        errors = field.check()
        expected = [
            Error(
                "Invalid 'default' value: 'invalid' value must be either True or False.",
                hint=None,
                obj=field,
                id='fields.E008',
            ),
        ]
        self.assertEqual(errors, expected)


class CharFieldTests(IsolatedModelsTestCase, TestCase):

@@ -215,6 +232,22 @@ class CharFieldTests(IsolatedModelsTestCase, TestCase):
        ]
        self.assertEqual(errors, expected)

    def test_invalid_default(self):
        class Model(models.Model):
            field = models.CharField(max_length=10, default=None)

        field = Model._meta.get_field('field')
        errors = field.check()
        expected = [
            Error(
                "Invalid 'default' value: This field cannot be null.",
                hint=None,
                obj=field,
                id='fields.E008',
            ),
        ]
        self.assertEqual(errors, expected)


class DateFieldTests(IsolatedModelsTestCase, TestCase):

@@ -281,6 +314,25 @@ class DateFieldTests(IsolatedModelsTestCase, TestCase):
    def test_fix_default_value_tz(self):
        self.test_fix_default_value()

    def test_invalid_default(self):
        class Model(models.Model):
            field = models.DateField(default='invalid')

        field = Model._meta.get_field('field')
        errors = field.check()
        message = (
            "Invalid 'default' value: 'invalid' value has an invalid date format. It must be in YYYY-MM-DD format."
        )
        expected = [
            Error(
                message,
                hint=None,
                obj=field,
                id='fields.E008',
            ),
        ]
        self.assertEqual(errors, expected)


class DateTimeFieldTests(IsolatedModelsTestCase, TestCase):

@@ -419,6 +471,22 @@ class DecimalFieldTests(IsolatedModelsTestCase):
        expected = []
        self.assertEqual(errors, expected)

    def test_invalid_default(self):
        class Model(models.Model):
            field = models.DecimalField(max_digits=3, decimal_places=2, default=decimal.Decimal('20.00'))

        field = Model._meta.get_field('field')
        errors = field.check()
        expected = [
            Error(
                "Invalid 'default' value: Ensure that there are no more than 3 digits in total.",
                hint=None,
                obj=field,
                id='fields.E008',
            ),
        ]
        self.assertEqual(errors, expected)


class FileFieldTests(IsolatedModelsTestCase):