Ticket #3257: related_choice_field_empty_label.patch
File related_choice_field_empty_label.patch, 7.8 KB (added by , 18 years ago) |
---|
-
django/db/models/fields/related.py
553 553 setattr(cls, related.get_accessor_name(), ForeignRelatedObjectsDescriptor(related)) 554 554 555 555 def formfield(self, **kwargs): 556 defaults = {' choices': self.get_choices_default(), 'required': not self.blank, 'label': capfirst(self.verbose_name), 'help_text': self.help_text}556 defaults = {'queryset': self.rel.to._default_manager.all(), 'required': not self.blank, 'label': capfirst(self.verbose_name), 'help_text': self.help_text} 557 557 defaults.update(kwargs) 558 return forms. ChoiceField(**defaults)558 return forms.ModelChoiceField(**defaults) 559 559 560 560 class OneToOneField(RelatedField, IntegerField): 561 561 def __init__(self, to, to_field=None, **kwargs): … … 619 619 cls._meta.one_to_one_field = self 620 620 621 621 def formfield(self, **kwargs): 622 defaults = {' choices': self.get_choices_default(), 'required': not self.blank, 'label': capfirst(self.verbose_name), 'help_text': self.help_text}622 defaults = {'queryset': self.rel.to._default_manager.all(), 'required': not self.blank, 'label': capfirst(self.verbose_name), 'help_text': self.help_text} 623 623 defaults.update(kwargs) 624 return forms. ChoiceField(**kwargs)624 return forms.ModelChoiceField(**kwargs) 625 625 626 626 class ManyToManyField(RelatedField, Field): 627 627 def __init__(self, to, **kwargs): … … 742 742 # MultipleChoiceField takes a list of IDs. 743 743 if kwargs.get('initial') is not None: 744 744 kwargs['initial'] = [i._get_pk_val() for i in kwargs['initial']] 745 defaults = {' choices': self.get_choices_default(), 'required': not self.blank, 'label': capfirst(self.verbose_name), 'help_text': self.help_text}745 defaults = {'queryset' : self.rel.to._default_manager.all(), 'required': not self.blank, 'label': capfirst(self.verbose_name), 'help_text': self.help_text} 746 746 defaults.update(kwargs) 747 return forms.M ultipleChoiceField(**defaults)747 return forms.ModelMultipleChoiceField(**defaults) 748 748 749 749 class ManyToOneRel(object): 750 750 def __init__(self, to, field_name, num_in_admin=3, min_num_in_admin=None, -
django/newforms/models.py
4 4 """ 5 5 6 6 from forms import BaseForm, DeclarativeFieldsMetaclass, SortedDictFromList 7 from fields import ChoiceField, MultipleChoiceField 8 from widgets import Select, SelectMultiple 7 9 8 __all__ = ('save_instance', 'form_for_model', 'form_for_instance', 'form_for_fields') 10 __all__ = ('save_instance', 'form_for_model', 'form_for_instance', 'form_for_fields', 11 'ModelChoiceField', 'ModelMultipleChoiceField') 9 12 10 13 def model_save(self, commit=True): 11 14 """ … … 33 36 for f in opts.fields: 34 37 if isinstance(f, models.AutoField): 35 38 continue 36 setattr(instance, f. attname, clean_data[f.name])39 setattr(instance, f.name, clean_data[f.name]) 37 40 if commit: 38 41 instance.save() 39 42 for f in opts.many_to_many: … … 96 99 "Returns a Form class for the given list of Django database field instances." 97 100 fields = SortedDictFromList([(f.name, f.formfield()) for f in field_list]) 98 101 return type('FormForFields', (BaseForm,), {'base_fields': fields}) 102 103 class ModelChoiceField(ChoiceField): 104 def __init__(self, queryset, empty_label=u"---------", **kwargs): 105 self.model = queryset.model 106 choices=[(obj._get_pk_val(), str(obj)) for obj in queryset] 107 if not empty_label is None: 108 choices = [(u"", empty_label)] + choices 109 ChoiceField.__init__(self, choices=choices, **kwargs) 110 111 def clean(self, value): 112 new_value = ChoiceField.clean(self, value) 113 if not new_value: 114 return None 115 try: 116 new_value = self.model._default_manager.get(pk=new_value) 117 except: 118 raise ValidationError(gettext(u'Select a valid choice. %s is not one of the available choices.') % value) 119 return new_value 120 121 class ModelMultipleChoiceField(MultipleChoiceField): 122 def __init__(self, queryset, **kwargs): 123 self.model = queryset.model 124 MultipleChoiceField.__init__(self, choices=[(obj._get_pk_val(), str(obj)) for obj in queryset], **kwargs) 125 126 def clean(self, value): 127 new_value = MultipleChoiceField.clean(self, value) 128 if not new_value: 129 return [] 130 return self.model._default_manager.filter(pk__in=new_value) -
tests/modeltests/model_forms/models.py
24 24 25 25 from django.db import models 26 26 27 class Poll(models.Model): 28 question = models.CharField(maxlength=200) 29 def __str__(self): 30 return "Q: %s " % self.question 31 27 32 class Category(models.Model): 28 33 name = models.CharField(maxlength=20) 29 34 url = models.CharField('The URL', maxlength=40) … … 281 286 <Category: Third> 282 287 >>> Category.objects.get(id=3) 283 288 <Category: Third> 289 290 # ModelChoiceField ################################################################# 291 292 >>> from django.newforms import * 293 294 >>> p = Poll(question="Test Question") 295 >>> p.save() 296 >>> p2 = Poll(question="Second Test Question") 297 >>> p2.save() 298 299 >>> f = ModelChoiceField(Poll.objects.all()) 300 >>> f.clean('') 301 Traceback (most recent call last): 302 ... 303 ValidationError: [u'This field is required.'] 304 >>> f.clean(None) 305 Traceback (most recent call last): 306 ... 307 ValidationError: [u'This field is required.'] 308 >>> f.clean(0) 309 Traceback (most recent call last): 310 ... 311 ValidationError: [u'Select a valid choice. 0 is not one of the available choices.'] 312 >>> f.clean(1) 313 <Poll: Q: Test Question > 314 >>> f.clean(2) 315 <Poll: Q: Second Test Question > 316 317 >>> f = ModelChoiceField(Poll.objects.filter( pk=1 ), required=False) 318 >>> print f.clean('') 319 None 320 >>> f.clean('') 321 >>> f.clean('1') 322 <Poll: Q: Test Question > 323 >>> f.clean('2') 324 Traceback (most recent call last): 325 ... 326 ValidationError: [u'Select a valid choice. 2 is not one of the available choices.'] 327 328 # ModelMultipleChoiceField ######################################################### 329 330 >>> f = ModelMultipleChoiceField(Poll.objects.all()) 331 >>> f.clean(None) 332 Traceback (most recent call last): 333 ... 334 ValidationError: [u'This field is required.'] 335 >>> f.clean([]) 336 Traceback (most recent call last): 337 ... 338 ValidationError: [u'This field is required.'] 339 >>> f.clean([1]) 340 [<Poll: Q: Test Question >] 341 >>> f.clean([2]) 342 [<Poll: Q: Second Test Question >] 343 >>> f.clean(['1']) 344 [<Poll: Q: Test Question >] 345 >>> f.clean(['1', '2']) 346 [<Poll: Q: Test Question >, <Poll: Q: Second Test Question >] 347 >>> f.clean([1, '2']) 348 [<Poll: Q: Test Question >, <Poll: Q: Second Test Question >] 349 >>> f.clean((1, '2')) 350 [<Poll: Q: Test Question >, <Poll: Q: Second Test Question >] 351 >>> f.clean('hello') 352 Traceback (most recent call last): 353 ... 354 ValidationError: [u'Enter a list of values.'] 355 >>> f = ModelMultipleChoiceField(Poll.objects.all(), required=False) 356 >>> f.clean([]) 357 [] 358 >>> f.clean(()) 359 [] 360 >>> f.clean(['3']) 361 Traceback (most recent call last): 362 ... 363 ValidationError: [u'Select a valid choice. 3 is not one of the available choices.'] 364 >>> f.clean(['3', '4']) 365 Traceback (most recent call last): 366 ... 367 ValidationError: [u'Select a valid choice. 3 is not one of the available choices.'] 368 >>> f.clean(['1', '5']) 369 Traceback (most recent call last): 370 ... 371 ValidationError: [u'Select a valid choice. 5 is not one of the available choices.'] 284 372 """}