From 75c8c1de9a8080ed1c47d39797c1cd779629be75 Mon Sep 17 00:00:00 2001 From: Russell Keith-Magee Date: Fri, 12 Mar 2010 15:22:05 +0000 Subject: [PATCH] Fixed #12404 -- Improved model validation for CharField and DecimalField. Thanks to tiliv for the report, josh for the patch, and Leo for the tests. git-svn-id: http://code.djangoproject.com/svn/django/trunk@12768 bcc190cf-cafb-0310-a4f2-bffc1f526a37 --- django/core/management/validation.py | 25 +++++++++++++++++------ tests/modeltests/invalid_models/models.py | 16 ++++++++++++--- 2 files changed, 32 insertions(+), 9 deletions(-) diff --git a/django/core/management/validation.py b/django/core/management/validation.py index 554c59e856..f0a9056871 100644 --- a/django/core/management/validation.py +++ b/django/core/management/validation.py @@ -37,13 +37,26 @@ def get_validation_errors(outfile, app=None): e.add(opts, '"%s": You can\'t use "id" as a field name, because each model automatically gets an "id" field if none of the fields have primary_key=True. You need to either remove/rename your "id" field or add primary_key=True to a field.' % f.name) if f.name.endswith('_'): e.add(opts, '"%s": Field names cannot end with underscores, because this would lead to ambiguous queryset filters.' % f.name) - if isinstance(f, models.CharField) and f.max_length in (None, 0): - e.add(opts, '"%s": CharFields require a "max_length" attribute.' % f.name) + if isinstance(f, models.CharField): + try: + max_length = int(f.max_length) + if max_length <= 0: + e.add(opts, '"%s": CharFields require a "max_length" attribute that is a positive integer.' % f.name) + except (ValueError, TypeError): + e.add(opts, '"%s": CharFields require a "max_length" attribute that is a positive integer.' % f.name) if isinstance(f, models.DecimalField): - if f.decimal_places is None: - e.add(opts, '"%s": DecimalFields require a "decimal_places" attribute.' % f.name) - if f.max_digits is None: - e.add(opts, '"%s": DecimalFields require a "max_digits" attribute.' % f.name) + try: + decimal_places = int(f.decimal_places) + if decimal_places <= 0: + e.add(opts, '"%s": DecimalFields require a "decimal_places" attribute that is a positive integer.' % f.name) + except (ValueError, TypeError): + e.add(opts, '"%s": DecimalFields require a "decimal_places" attribute that is a positive integer.' % f.name) + try: + max_digits = int(f.max_digits) + if max_digits <= 0: + e.add(opts, '"%s": DecimalFields require a "max_digits" attribute that is a positive integer.' % f.name) + except (ValueError, TypeError): + e.add(opts, '"%s": DecimalFields require a "max_digits" attribute that is a positive integer.' % f.name) if isinstance(f, models.FileField) and not f.upload_to: e.add(opts, '"%s": FileFields require an "upload_to" attribute.' % f.name) if isinstance(f, models.ImageField): diff --git a/tests/modeltests/invalid_models/models.py b/tests/modeltests/invalid_models/models.py index 8aa7678930..26c393be96 100644 --- a/tests/modeltests/invalid_models/models.py +++ b/tests/modeltests/invalid_models/models.py @@ -8,7 +8,11 @@ from django.db import models class FieldErrors(models.Model): charfield = models.CharField() + charfield2 = models.CharField(max_length=-1) + charfield3 = models.CharField(max_length="bad") decimalfield = models.DecimalField() + decimalfield2 = models.DecimalField(max_digits=-1, decimal_places=-1) + decimalfield3 = models.DecimalField(max_digits="bad", decimal_places="bad") filefield = models.FileField() choices = models.CharField(max_length=10, choices='bad') choices2 = models.CharField(max_length=10, choices=[(1,2,3),(1,2,3)]) @@ -203,9 +207,15 @@ class UniqueFKTarget2(models.Model): tgt = models.ForeignKey(FKTarget, to_field='good') -model_errors = """invalid_models.fielderrors: "charfield": CharFields require a "max_length" attribute. -invalid_models.fielderrors: "decimalfield": DecimalFields require a "decimal_places" attribute. -invalid_models.fielderrors: "decimalfield": DecimalFields require a "max_digits" attribute. +model_errors = """invalid_models.fielderrors: "charfield": CharFields require a "max_length" attribute that is a positive integer. +invalid_models.fielderrors: "charfield2": CharFields require a "max_length" attribute that is a positive integer. +invalid_models.fielderrors: "charfield3": CharFields require a "max_length" attribute that is a positive integer. +invalid_models.fielderrors: "decimalfield": DecimalFields require a "decimal_places" attribute that is a positive integer. +invalid_models.fielderrors: "decimalfield": DecimalFields require a "max_digits" attribute that is a positive integer. +invalid_models.fielderrors: "decimalfield2": DecimalFields require a "decimal_places" attribute that is a positive integer. +invalid_models.fielderrors: "decimalfield2": DecimalFields require a "max_digits" attribute that is a positive integer. +invalid_models.fielderrors: "decimalfield3": DecimalFields require a "decimal_places" attribute that is a positive integer. +invalid_models.fielderrors: "decimalfield3": DecimalFields require a "max_digits" attribute that is a positive integer. invalid_models.fielderrors: "filefield": FileFields require an "upload_to" attribute. invalid_models.fielderrors: "choices": "choices" should be iterable (e.g., a tuple or list). invalid_models.fielderrors: "choices2": "choices" should be a sequence of two-tuples.