Skip to content
This repository

HTTPS clone URL

Subversion checkout URL

You can clone with HTTPS or Subversion.

Download ZIP
Browse code

Fixed #4787, #5913 -- Updating the queryset on a `ModelChoiceField` o…

…r `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
  • Loading branch information...
commit babfe78494028415b0e5f74ec2ca9b66506e8d34 1 parent 5e8be69
Gary Wilson Jr. authored November 13, 2007
14  django/newforms/models.py
@@ -155,14 +155,22 @@ class ModelChoiceField(ChoiceField):
155 155
     def __init__(self, queryset, empty_label=u"---------", cache_choices=False,
156 156
                  required=True, widget=Select, label=None, initial=None,
157 157
                  help_text=None):
158  
-        self.queryset = queryset
159 158
         self.empty_label = empty_label
160 159
         self.cache_choices = cache_choices
161 160
         # Call Field instead of ChoiceField __init__() because we don't need
162 161
         # ChoiceField.__init__().
163 162
         Field.__init__(self, required, widget, label, initial, help_text)
  163
+        self.queryset = queryset
  164
+
  165
+    def _get_queryset(self):
  166
+        return self._queryset
  167
+
  168
+    def _set_queryset(self, queryset):
  169
+        self._queryset = queryset
164 170
         self.widget.choices = self.choices
165 171
 
  172
+    queryset = property(_get_queryset, _set_queryset)
  173
+
166 174
     def _get_choices(self):
167 175
         # If self._choices is set, then somebody must have manually set
168 176
         # the property self.choices. In this case, just return self._choices.
@@ -190,7 +198,7 @@ def clean(self, value):
190 198
         if value in ('', None):
191 199
             return None
192 200
         try:
193  
-            value = self.queryset.model._default_manager.get(pk=value)
  201
+            value = self.queryset.get(pk=value)
194 202
         except self.queryset.model.DoesNotExist:
195 203
             raise ValidationError(ugettext(u'Select a valid choice. That'
196 204
                                            u' choice is not one of the'
@@ -217,7 +225,7 @@ def clean(self, value):
217 225
         final_values = []
218 226
         for val in value:
219 227
             try:
220  
-                obj = self.queryset.model._default_manager.get(pk=val)
  228
+                obj = self.queryset.get(pk=val)
221 229
             except self.queryset.model.DoesNotExist:
222 230
                 raise ValidationError(ugettext(u'Select a valid choice. %s is'
223 231
                                                u' not one of the available'
32  tests/modeltests/model_forms/models.py
@@ -440,6 +440,8 @@ def __unicode__(self):
440 440
 >>> from django.newforms import ModelChoiceField, ModelMultipleChoiceField
441 441
 
442 442
 >>> f = ModelChoiceField(Category.objects.all())
  443
+>>> list(f.choices)
  444
+[(u'', u'---------'), (1, u'Entertainment'), (2, u"It's a test"), (3, u'Third'), (4, u'Fourth')]
443 445
 >>> f.clean('')
444 446
 Traceback (most recent call last):
445 447
 ...
@@ -485,9 +487,23 @@ def __unicode__(self):
485 487
 ...
486 488
 ValidationError: [u'Select a valid choice. That choice is not one of the available choices.']
487 489
 
  490
+# queryset can be changed after the field is created.
  491
+>>> f.queryset = Category.objects.exclude(name='Fourth')
  492
+>>> list(f.choices)
  493
+[(u'', u'---------'), (1, u'Entertainment'), (2, u"It's a test"), (3, u'Third')]
  494
+>>> f.clean(3)
  495
+<Category: Third>
  496
+>>> f.clean(4)
  497
+Traceback (most recent call last):
  498
+...
  499
+ValidationError: [u'Select a valid choice. That choice is not one of the available choices.']
  500
+
  501
+
488 502
 # ModelMultipleChoiceField ####################################################
489 503
 
490 504
 >>> f = ModelMultipleChoiceField(Category.objects.all())
  505
+>>> list(f.choices)
  506
+[(1, u'Entertainment'), (2, u"It's a test"), (3, u'Third'), (4, u'Fourth')]
491 507
 >>> f.clean(None)
492 508
 Traceback (most recent call last):
493 509
 ...
@@ -552,6 +568,22 @@ def __unicode__(self):
552 568
 ...
553 569
 ValidationError: [u'Select a valid choice. 10 is not one of the available choices.']
554 570
 
  571
+# queryset can be changed after the field is created.
  572
+>>> f.queryset = Category.objects.exclude(name='Fourth')
  573
+>>> list(f.choices)
  574
+[(1, u'Entertainment'), (2, u"It's a test"), (3, u'Third')]
  575
+>>> f.clean([3])
  576
+[<Category: Third>]
  577
+>>> f.clean([4])
  578
+Traceback (most recent call last):
  579
+...
  580
+ValidationError: [u'Select a valid choice. 4 is not one of the available choices.']
  581
+>>> f.clean(['3', '4'])
  582
+Traceback (most recent call last):
  583
+...
  584
+ValidationError: [u'Select a valid choice. 4 is not one of the available choices.']
  585
+
  586
+
555 587
 # PhoneNumberField ############################################################
556 588
 
557 589
 >>> PhoneNumberForm = form_for_model(PhoneNumber)

0 notes on commit babfe78

Please sign in to comment.
Something went wrong with that request. Please try again.