Changeset 7326
- Timestamp:
- 03/19/08 18:10:45 (1 year ago)
- Files:
-
- django/trunk/django/newforms/models.py (modified) (4 diffs)
- django/trunk/docs/newforms.txt (modified) (1 diff)
- django/trunk/tests/modeltests/model_forms/models.py (modified) (2 diffs)
Legend:
- Unmodified
- Added
- Removed
- Modified
- Copied
- Moved
django/trunk/django/newforms/models.py
r7117 r7326 278 278 # Fields ##################################################################### 279 279 280 class QuerySetIterator(object): 281 def __init__(self, queryset, empty_label, cache_choices): 282 self.queryset = queryset 283 self.empty_label = empty_label 284 self.cache_choices = cache_choices 280 class ModelChoiceIterator(object): 281 def __init__(self, field): 282 self.field = field 283 self.queryset = field.queryset 285 284 286 285 def __iter__(self): 287 if self. empty_label is not None:288 yield (u"", self. empty_label)286 if self.field.empty_label is not None: 287 yield (u"", self.field.empty_label) 289 288 for obj in self.queryset: 290 yield (obj.pk, s mart_unicode(obj))289 yield (obj.pk, self.field.label_from_instance(obj)) 291 290 # Clear the QuerySet cache if required. 292 if not self. cache_choices:291 if not self.field.cache_choices: 293 292 self.queryset._result_cache = None 294 293 … … 307 306 self.empty_label = empty_label 308 307 self.cache_choices = cache_choices 308 309 309 # Call Field instead of ChoiceField __init__() because we don't need 310 310 # ChoiceField.__init__(). … … 322 322 queryset = property(_get_queryset, _set_queryset) 323 323 324 # this method will be used to create object labels by the QuerySetIterator. 325 # Override it to customize the label. 326 def label_from_instance(self, obj): 327 """ 328 This method is used to convert objects into strings; it's used to 329 generate the labels for the choices presented by this object. Subclasses 330 can override this method to customize the display of the choices. 331 """ 332 return smart_unicode(obj) 333 324 334 def _get_choices(self): 325 335 # If self._choices is set, then somebody must have manually set … … 327 337 if hasattr(self, '_choices'): 328 338 return self._choices 339 329 340 # Otherwise, execute the QuerySet in self.queryset to determine the 330 # choices dynamically. Return a fresh QuerySetIterator that has not 331 # been consumed. Note that we're instantiating a new QuerySetIterator332 # *each* time _get_choices() is called (and, thus, each time333 # self.choices is accessed) so that we can ensure the QuerySet has not334 # been consumed.335 return QuerySetIterator(self.queryset, self.empty_label,336 self.cache_choices)341 # choices dynamically. Return a fresh QuerySetIterator that has not been 342 # consumed. Note that we're instantiating a new QuerySetIterator *each* 343 # time _get_choices() is called (and, thus, each time self.choices is 344 # accessed) so that we can ensure the QuerySet has not been consumed. This 345 # construct might look complicated but it allows for lazy evaluation of 346 # the queryset. 347 return ModelChoiceIterator(self) 337 348 338 349 def _set_choices(self, value): django/trunk/docs/newforms.txt
r7323 r7326 1550 1550 ~~~~~~~~~~~~~~~~~~~~ 1551 1551 1552 Allows the selection of a single model object, suitable for 1553 representing a foreign key. 1552 Allows the selection of a single model object, suitable for representing a 1553 foreign key. The method receives an object as an argument and must return a 1554 string to represent it. 1555 1556 The labels for the choice field call the ``__unicode__`` method of the model to 1557 generate string representations. To provide custom labels, subclass ``ModelChoiceField`` and override ``label_for_model``:: 1558 1559 class MyModelChoiceField(ModelChoiceField): 1560 def label_from_instance(self, obj): 1561 return "My Object #%i" % obj.id 1554 1562 1555 1563 ``ModelMultipleChoiceField`` 1556 1564 ~~~~~~~~~~~~~~~~~~~~~~~~~~~~ 1557 1565 1558 Allows the selection of one or more model objects, suitable for 1559 representing a many-to-many relation. 1560 1566 Allows the selection of one or more model objects, suitable for representing a 1567 many-to-many relation. As with ``ModelChoiceField``, you can use 1568 ``label_from_instance`` to customize the object labels. 1561 1569 1562 1570 Creating custom fields django/trunk/tests/modeltests/model_forms/models.py
r7322 r7326 660 660 ValidationError: [u'Select a valid choice. That choice is not one of the available choices.'] 661 661 662 # check that we can safely iterate choices repeatedly 663 >>> gen_one = list(f.choices) 664 >>> gen_two = f.choices 665 >>> gen_one[2] 666 (2L, u"It's a test") 667 >>> list(gen_two) 668 [(u'', u'---------'), (1L, u'Entertainment'), (2L, u"It's a test"), (3L, u'Third')] 669 670 # check that we can override the label_from_instance method to print custom labels (#4620) 671 >>> f.queryset = Category.objects.all() 672 >>> f.label_from_instance = lambda obj: "category " + str(obj) 673 >>> list(f.choices) 674 [(u'', u'---------'), (1L, 'category Entertainment'), (2L, "category It's a test"), (3L, 'category Third'), (4L, 'category Fourth')] 662 675 663 676 # ModelMultipleChoiceField #################################################### … … 745 758 ValidationError: [u'Select a valid choice. 4 is not one of the available choices.'] 746 759 760 >>> f.queryset = Category.objects.all() 761 >>> f.label_from_instance = lambda obj: "multicategory " + str(obj) 762 >>> list(f.choices) 763 [(1L, 'multicategory Entertainment'), (2L, "multicategory It's a test"), (3L, 'multicategory Third'), (4L, 'multicategory Fourth')] 747 764 748 765 # PhoneNumberField ############################################################
