Fixed #4787, #5913 -- Updating the queryset on a `ModelChoiceField` or `ModelMultipleChoiceField` now updates its widget's choices. The clean methods for `ModelChoiceField` and `ModelMultipleChoiceField` were changed to only allow choices in the specified queryset (instead of allowing all choices returned by the queryset model's default manager).
git-svn-id: http://code.djangoproject.com/svn/django/trunk@6670 bcc190cf-cafb-0310-a4f2-bffc1f526a37
This commit is contained in:
parent
5e8be6978e
commit
babfe78494
|
@ -155,14 +155,22 @@ class ModelChoiceField(ChoiceField):
|
||||||
def __init__(self, queryset, empty_label=u"---------", cache_choices=False,
|
def __init__(self, queryset, empty_label=u"---------", cache_choices=False,
|
||||||
required=True, widget=Select, label=None, initial=None,
|
required=True, widget=Select, label=None, initial=None,
|
||||||
help_text=None):
|
help_text=None):
|
||||||
self.queryset = queryset
|
|
||||||
self.empty_label = empty_label
|
self.empty_label = empty_label
|
||||||
self.cache_choices = cache_choices
|
self.cache_choices = cache_choices
|
||||||
# Call Field instead of ChoiceField __init__() because we don't need
|
# Call Field instead of ChoiceField __init__() because we don't need
|
||||||
# ChoiceField.__init__().
|
# ChoiceField.__init__().
|
||||||
Field.__init__(self, required, widget, label, initial, help_text)
|
Field.__init__(self, required, widget, label, initial, help_text)
|
||||||
|
self.queryset = queryset
|
||||||
|
|
||||||
|
def _get_queryset(self):
|
||||||
|
return self._queryset
|
||||||
|
|
||||||
|
def _set_queryset(self, queryset):
|
||||||
|
self._queryset = queryset
|
||||||
self.widget.choices = self.choices
|
self.widget.choices = self.choices
|
||||||
|
|
||||||
|
queryset = property(_get_queryset, _set_queryset)
|
||||||
|
|
||||||
def _get_choices(self):
|
def _get_choices(self):
|
||||||
# If self._choices is set, then somebody must have manually set
|
# If self._choices is set, then somebody must have manually set
|
||||||
# the property self.choices. In this case, just return self._choices.
|
# the property self.choices. In this case, just return self._choices.
|
||||||
|
@ -190,7 +198,7 @@ class ModelChoiceField(ChoiceField):
|
||||||
if value in ('', None):
|
if value in ('', None):
|
||||||
return None
|
return None
|
||||||
try:
|
try:
|
||||||
value = self.queryset.model._default_manager.get(pk=value)
|
value = self.queryset.get(pk=value)
|
||||||
except self.queryset.model.DoesNotExist:
|
except self.queryset.model.DoesNotExist:
|
||||||
raise ValidationError(ugettext(u'Select a valid choice. That'
|
raise ValidationError(ugettext(u'Select a valid choice. That'
|
||||||
u' choice is not one of the'
|
u' choice is not one of the'
|
||||||
|
@ -217,7 +225,7 @@ class ModelMultipleChoiceField(ModelChoiceField):
|
||||||
final_values = []
|
final_values = []
|
||||||
for val in value:
|
for val in value:
|
||||||
try:
|
try:
|
||||||
obj = self.queryset.model._default_manager.get(pk=val)
|
obj = self.queryset.get(pk=val)
|
||||||
except self.queryset.model.DoesNotExist:
|
except self.queryset.model.DoesNotExist:
|
||||||
raise ValidationError(ugettext(u'Select a valid choice. %s is'
|
raise ValidationError(ugettext(u'Select a valid choice. %s is'
|
||||||
u' not one of the available'
|
u' not one of the available'
|
||||||
|
|
|
@ -440,6 +440,8 @@ the data in the database when the form is instantiated.
|
||||||
>>> from django.newforms import ModelChoiceField, ModelMultipleChoiceField
|
>>> from django.newforms import ModelChoiceField, ModelMultipleChoiceField
|
||||||
|
|
||||||
>>> f = ModelChoiceField(Category.objects.all())
|
>>> f = ModelChoiceField(Category.objects.all())
|
||||||
|
>>> list(f.choices)
|
||||||
|
[(u'', u'---------'), (1, u'Entertainment'), (2, u"It's a test"), (3, u'Third'), (4, u'Fourth')]
|
||||||
>>> f.clean('')
|
>>> f.clean('')
|
||||||
Traceback (most recent call last):
|
Traceback (most recent call last):
|
||||||
...
|
...
|
||||||
|
@ -485,9 +487,23 @@ Traceback (most recent call last):
|
||||||
...
|
...
|
||||||
ValidationError: [u'Select a valid choice. That choice is not one of the available choices.']
|
ValidationError: [u'Select a valid choice. That choice is not one of the available choices.']
|
||||||
|
|
||||||
|
# queryset can be changed after the field is created.
|
||||||
|
>>> f.queryset = Category.objects.exclude(name='Fourth')
|
||||||
|
>>> list(f.choices)
|
||||||
|
[(u'', u'---------'), (1, u'Entertainment'), (2, u"It's a test"), (3, u'Third')]
|
||||||
|
>>> f.clean(3)
|
||||||
|
<Category: Third>
|
||||||
|
>>> f.clean(4)
|
||||||
|
Traceback (most recent call last):
|
||||||
|
...
|
||||||
|
ValidationError: [u'Select a valid choice. That choice is not one of the available choices.']
|
||||||
|
|
||||||
|
|
||||||
# ModelMultipleChoiceField ####################################################
|
# ModelMultipleChoiceField ####################################################
|
||||||
|
|
||||||
>>> f = ModelMultipleChoiceField(Category.objects.all())
|
>>> f = ModelMultipleChoiceField(Category.objects.all())
|
||||||
|
>>> list(f.choices)
|
||||||
|
[(1, u'Entertainment'), (2, u"It's a test"), (3, u'Third'), (4, u'Fourth')]
|
||||||
>>> f.clean(None)
|
>>> f.clean(None)
|
||||||
Traceback (most recent call last):
|
Traceback (most recent call last):
|
||||||
...
|
...
|
||||||
|
@ -552,6 +568,22 @@ Traceback (most recent call last):
|
||||||
...
|
...
|
||||||
ValidationError: [u'Select a valid choice. 10 is not one of the available choices.']
|
ValidationError: [u'Select a valid choice. 10 is not one of the available choices.']
|
||||||
|
|
||||||
|
# queryset can be changed after the field is created.
|
||||||
|
>>> f.queryset = Category.objects.exclude(name='Fourth')
|
||||||
|
>>> list(f.choices)
|
||||||
|
[(1, u'Entertainment'), (2, u"It's a test"), (3, u'Third')]
|
||||||
|
>>> f.clean([3])
|
||||||
|
[<Category: Third>]
|
||||||
|
>>> f.clean([4])
|
||||||
|
Traceback (most recent call last):
|
||||||
|
...
|
||||||
|
ValidationError: [u'Select a valid choice. 4 is not one of the available choices.']
|
||||||
|
>>> f.clean(['3', '4'])
|
||||||
|
Traceback (most recent call last):
|
||||||
|
...
|
||||||
|
ValidationError: [u'Select a valid choice. 4 is not one of the available choices.']
|
||||||
|
|
||||||
|
|
||||||
# PhoneNumberField ############################################################
|
# PhoneNumberField ############################################################
|
||||||
|
|
||||||
>>> PhoneNumberForm = form_for_model(PhoneNumber)
|
>>> PhoneNumberForm = form_for_model(PhoneNumber)
|
||||||
|
|
Loading…
Reference in New Issue