From b2b6fc8e3c78671c8b6af2709358c3213c84d119 Mon Sep 17 00:00:00 2001 From: Gary Wilson Jr Date: Sun, 18 Nov 2007 20:25:23 +0000 Subject: [PATCH] Fixed #5975 -- Gave `ModelChoiceField` and `ModelMultipleChoiceField` ability to specify custom error messages. git-svn-id: http://code.djangoproject.com/svn/django/trunk@6694 bcc190cf-cafb-0310-a4f2-bffc1f526a37 --- django/newforms/models.py | 33 ++++++++------ tests/regressiontests/forms/error_messages.py | 45 +++++++++++++++++++ tests/regressiontests/forms/models.py | 4 ++ 3 files changed, 69 insertions(+), 13 deletions(-) diff --git a/django/newforms/models.py b/django/newforms/models.py index c86b9b3a42f..4c783e4e9d2 100644 --- a/django/newforms/models.py +++ b/django/newforms/models.py @@ -3,7 +3,7 @@ Helper functions for creating Form classes from Django models and database field objects. """ -from django.utils.translation import ugettext +from django.utils.translation import ugettext_lazy as _ from django.utils.encoding import smart_unicode from django.utils.datastructures import SortedDict @@ -151,15 +151,20 @@ class ModelChoiceField(ChoiceField): """A ChoiceField whose choices are a model QuerySet.""" # This class is a subclass of ChoiceField for purity, but it doesn't # actually use any of ChoiceField's implementation. + default_error_messages = { + 'invalid_choice': _(u'Select a valid choice. That choice is not one of' + u' the available choices.'), + } def __init__(self, queryset, empty_label=u"---------", cache_choices=False, required=True, widget=Select, label=None, initial=None, - help_text=None): + help_text=None, *args, **kwargs): self.empty_label = empty_label self.cache_choices = cache_choices # Call Field instead of ChoiceField __init__() because we don't need # ChoiceField.__init__(). - Field.__init__(self, required, widget, label, initial, help_text) + Field.__init__(self, required, widget, label, initial, help_text, + *args, **kwargs) self.queryset = queryset def _get_queryset(self): @@ -200,36 +205,38 @@ class ModelChoiceField(ChoiceField): try: value = self.queryset.get(pk=value) except self.queryset.model.DoesNotExist: - raise ValidationError(ugettext(u'Select a valid choice. That' - u' choice is not one of the' - u' available choices.')) + raise ValidationError(self.error_messages['invalid_choice']) return value class ModelMultipleChoiceField(ModelChoiceField): """A MultipleChoiceField whose choices are a model QuerySet.""" hidden_widget = MultipleHiddenInput + default_error_messages = { + 'list': _(u'Enter a list of values.'), + 'invalid_choice': _(u'Select a valid choice. %s is not one of the' + u' available choices.'), + } def __init__(self, queryset, cache_choices=False, required=True, widget=SelectMultiple, label=None, initial=None, - help_text=None): + help_text=None, *args, **kwargs): super(ModelMultipleChoiceField, self).__init__(queryset, None, - cache_choices, required, widget, label, initial, help_text) + cache_choices, required, widget, label, initial, help_text, + *args, **kwargs) def clean(self, value): if self.required and not value: - raise ValidationError(ugettext(u'This field is required.')) + raise ValidationError(self.error_messages['required']) elif not self.required and not value: return [] if not isinstance(value, (list, tuple)): - raise ValidationError(ugettext(u'Enter a list of values.')) + raise ValidationError(self.error_messages['list']) final_values = [] for val in value: try: obj = self.queryset.get(pk=val) except self.queryset.model.DoesNotExist: - raise ValidationError(ugettext(u'Select a valid choice. %s is' - u' not one of the available' - u' choices.') % val) + raise ValidationError(self.error_messages['invalid_choice'] % val) else: final_values.append(obj) return final_values diff --git a/tests/regressiontests/forms/error_messages.py b/tests/regressiontests/forms/error_messages.py index ff7e110f6fe..9f972f5b908 100644 --- a/tests/regressiontests/forms/error_messages.py +++ b/tests/regressiontests/forms/error_messages.py @@ -312,4 +312,49 @@ ValidationError: [u'REQUIRED'] Traceback (most recent call last): ... ValidationError: [u'INVALID IP ADDRESS'] + +############################################################################### + +# Create choices for the model choice field tests below. + +>>> from regressiontests.forms.models import ChoiceModel +>>> ChoiceModel.objects.create(pk=1, name='a') + +>>> ChoiceModel.objects.create(pk=2, name='b') + +>>> ChoiceModel.objects.create(pk=3, name='c') + + +# ModelChoiceField ############################################################ + +>>> e = {'required': 'REQUIRED'} +>>> e['invalid_choice'] = 'INVALID CHOICE' +>>> f = ModelChoiceField(queryset=ChoiceModel.objects.all(), error_messages=e) +>>> f.clean('') +Traceback (most recent call last): +... +ValidationError: [u'REQUIRED'] +>>> f.clean('4') +Traceback (most recent call last): +... +ValidationError: [u'INVALID CHOICE'] + +# ModelMultipleChoiceField #################################################### + +>>> e = {'required': 'REQUIRED'} +>>> e['invalid_choice'] = '%s IS INVALID CHOICE' +>>> e['list'] = 'NOT A LIST OF VALUES' +>>> f = ModelMultipleChoiceField(queryset=ChoiceModel.objects.all(), error_messages=e) +>>> f.clean('') +Traceback (most recent call last): +... +ValidationError: [u'REQUIRED'] +>>> f.clean('3') +Traceback (most recent call last): +... +ValidationError: [u'NOT A LIST OF VALUES'] +>>> f.clean(['4']) +Traceback (most recent call last): +... +ValidationError: [u'4 IS INVALID CHOICE'] """ diff --git a/tests/regressiontests/forms/models.py b/tests/regressiontests/forms/models.py index 1a6f566b6bb..c7ce1285604 100644 --- a/tests/regressiontests/forms/models.py +++ b/tests/regressiontests/forms/models.py @@ -10,6 +10,10 @@ class Defaults(models.Model): def_date = models.DateField(default = datetime.date(1980, 1, 1)) value = models.IntegerField(default=42) +class ChoiceModel(models.Model): + """For ModelChoiceField and ModelMultipleChoiceField tests.""" + name = models.CharField(max_length=10) + __test__ = {'API_TESTS': """ >>> from django.newforms import form_for_model, form_for_instance