Fix #15126: Better error message when passing invalid options to ModelForm.Meta.

This commit is contained in:
Baptiste Mispelon 2013-04-07 18:41:35 +02:00
parent 5ab66dea50
commit f9dc1379b8
2 changed files with 49 additions and 0 deletions

View File

@ -205,6 +205,21 @@ class ModelFormMetaclass(type):
if 'media' not in attrs: if 'media' not in attrs:
new_class.media = media_property(new_class) new_class.media = media_property(new_class)
opts = new_class._meta = ModelFormOptions(getattr(new_class, 'Meta', None)) opts = new_class._meta = ModelFormOptions(getattr(new_class, 'Meta', None))
# We check if a string was passed to `fields` or `exclude`,
# which is likely to be a mistake where the user typed ('foo') instead
# of ('foo',)
for opt in ['fields', 'exclude']:
value = getattr(opts, opt)
if isinstance(value, six.string_types):
msg = ("%(model)s.Meta.%(opt)s cannot be a string. "
"Did you mean to type: ('%(value)s',)?" % {
'model': new_class.__name__,
'opt': opt,
'value': value,
})
raise TypeError(msg)
if opts.model: if opts.model:
# If a model is defined, extract form fields from it. # If a model is defined, extract form fields from it.
fields = fields_for_model(opts.model, opts.fields, fields = fields_for_model(opts.model, opts.fields,

View File

@ -5,6 +5,7 @@ import os
from decimal import Decimal from decimal import Decimal
from django import forms from django import forms
from django.core.exceptions import FieldError
from django.core.files.uploadedfile import SimpleUploadedFile from django.core.files.uploadedfile import SimpleUploadedFile
from django.core.validators import ValidationError from django.core.validators import ValidationError
from django.db import connection from django.db import connection
@ -228,6 +229,22 @@ class ModelFormBaseTest(TestCase):
self.assertEqual(list(LimitFields.base_fields), self.assertEqual(list(LimitFields.base_fields),
['url']) ['url'])
def test_limit_nonexistent_field(self):
expected_msg = 'Unknown field(s) (nonexistent) specified for Category'
with self.assertRaisesMessage(FieldError, expected_msg):
class InvalidCategoryForm(forms.ModelForm):
class Meta:
model = Category
fields = ['nonexistent']
def test_limit_fields_with_string(self):
expected_msg = "CategoryForm.Meta.fields cannot be a string. Did you mean to type: ('url',)?"
with self.assertRaisesMessage(TypeError, expected_msg):
class CategoryForm(forms.ModelForm):
class Meta:
model = Category
fields = ('url') # note the missing comma
def test_exclude_fields(self): def test_exclude_fields(self):
class ExcludeFields(forms.ModelForm): class ExcludeFields(forms.ModelForm):
class Meta: class Meta:
@ -237,6 +254,23 @@ class ModelFormBaseTest(TestCase):
self.assertEqual(list(ExcludeFields.base_fields), self.assertEqual(list(ExcludeFields.base_fields),
['name', 'slug']) ['name', 'slug'])
def test_exclude_nonexistent_field(self):
class ExcludeFields(forms.ModelForm):
class Meta:
model = Category
exclude = ['nonexistent']
self.assertEqual(list(ExcludeFields.base_fields),
['name', 'slug', 'url'])
def test_exclude_fields_with_string(self):
expected_msg = "CategoryForm.Meta.exclude cannot be a string. Did you mean to type: ('url',)?"
with self.assertRaisesMessage(TypeError, expected_msg):
class CategoryForm(forms.ModelForm):
class Meta:
model = Category
exclude = ('url') # note the missing comma
def test_confused_form(self): def test_confused_form(self):
class ConfusedForm(forms.ModelForm): class ConfusedForm(forms.ModelForm):
""" Using 'fields' *and* 'exclude'. Not sure why you'd want to do """ Using 'fields' *and* 'exclude'. Not sure why you'd want to do