Django

Code

Changeset 4547

Show
Ignore:
Timestamp:
02/19/07 20:42:07 (2 years ago)
Author:
adrian
Message:

Fixed #3257 -- Added newforms ModelChoiceField? and ModelMultipleChoiceField?, which are now used by form_for_model() and form_for_instance(). Thanks for the patch, Honza Kral, floguy@gmail.com and kilian.cavalotti

Files:

Legend:

Unmodified
Added
Removed
Modified
Copied
Moved
  • django/trunk/django/db/models/fields/related.py

    r4486 r4547  
    554554 
    555555    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} 
    557557        defaults.update(kwargs) 
    558         return forms.ChoiceField(**defaults) 
     558        return forms.ModelChoiceField(**defaults) 
    559559 
    560560class OneToOneField(RelatedField, IntegerField): 
     
    620620 
    621621    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} 
    623623        defaults.update(kwargs) 
    624         return forms.ChoiceField(**kwargs) 
     624        return forms.ModelChoiceField(**kwargs) 
    625625 
    626626class ManyToManyField(RelatedField, Field): 
     
    743743        if kwargs.get('initial') is not None: 
    744744            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} 
    746746        defaults.update(kwargs) 
    747         return forms.MultipleChoiceField(**defaults) 
     747        return forms.ModelMultipleChoiceField(**defaults) 
    748748 
    749749class ManyToOneRel(object): 
  • django/trunk/django/newforms/models.py

    r4449 r4547  
    55 
    66from forms import BaseForm, DeclarativeFieldsMetaclass, SortedDictFromList 
     7from fields import ChoiceField, MultipleChoiceField 
     8from widgets import Select, SelectMultiple 
    79 
    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') 
    912 
    1013def model_save(self, commit=True): 
     
    3437        if isinstance(f, models.AutoField): 
    3538            continue 
    36         setattr(instance, f.attname, clean_data[f.name]) 
     39        setattr(instance, f.name, clean_data[f.name]) 
    3740    if commit: 
    3841        instance.save() 
     
    97100    fields = SortedDictFromList([(f.name, f.formfield()) for f in field_list]) 
    98101    return type('FormForFields', (BaseForm,), {'base_fields': fields}) 
     102 
     103class ModelChoiceField(ChoiceField): 
     104    "A ChoiceField whose choices are a model QuerySet." 
     105    def __init__(self, queryset, empty_label=u"---------", **kwargs): 
     106        self.model = queryset.model 
     107        choices = [(obj._get_pk_val(), str(obj)) for obj in queryset] 
     108        if empty_label is not None: 
     109            choices = [(u"", empty_label)] + choices 
     110        ChoiceField.__init__(self, choices=choices, **kwargs) 
     111 
     112    def clean(self, value): 
     113        value = ChoiceField.clean(self, value) 
     114        if not value: 
     115            return None 
     116        try: 
     117            value = self.model._default_manager.get(pk=value) 
     118        except self.model.DoesNotExist: 
     119            raise ValidationError(gettext(u'Select a valid choice. That choice is not one of the available choices.')) 
     120        return value 
     121 
     122class ModelMultipleChoiceField(MultipleChoiceField): 
     123    "A MultipleChoiceField whose choices are a model QuerySet." 
     124    def __init__(self, queryset, **kwargs): 
     125        self.model = queryset.model 
     126        MultipleChoiceField.__init__(self, choices=[(obj._get_pk_val(), str(obj)) for obj in queryset], **kwargs) 
     127 
     128    def clean(self, value): 
     129        value = MultipleChoiceField.clean(self, value) 
     130        if not value: 
     131            return [] 
     132        return self.model._default_manager.filter(pk__in=value) 
  • django/trunk/tests/modeltests/model_forms/models.py

    r4442 r4547  
    282282>>> Category.objects.get(id=3) 
    283283<Category: Third> 
     284 
     285# ModelChoiceField ############################################################ 
     286 
     287>>> from django.newforms import ModelChoiceField, ModelMultipleChoiceField 
     288 
     289>>> f = ModelChoiceField(Category.objects.all()) 
     290>>> f.clean('') 
     291Traceback (most recent call last): 
     292... 
     293ValidationError: [u'This field is required.'] 
     294>>> f.clean(None) 
     295Traceback (most recent call last): 
     296... 
     297ValidationError: [u'This field is required.'] 
     298>>> f.clean(0) 
     299Traceback (most recent call last): 
     300... 
     301ValidationError: [u'Select a valid choice. That choice is not one of the available choices.'] 
     302>>> f.clean(3) 
     303<Category: Third> 
     304>>> f.clean(2) 
     305<Category: It's a test> 
     306 
     307>>> f = ModelChoiceField(Category.objects.filter(pk=1), required=False) 
     308>>> print f.clean('') 
     309None 
     310>>> f.clean('') 
     311>>> f.clean('1') 
     312<Category: Entertainment> 
     313>>> f.clean('2') 
     314Traceback (most recent call last): 
     315... 
     316ValidationError: [u'Select a valid choice. That choice is not one of the available choices.'] 
     317 
     318# ModelMultipleChoiceField #################################################### 
     319 
     320>>> f = ModelMultipleChoiceField(Category.objects.all()) 
     321>>> f.clean(None) 
     322Traceback (most recent call last): 
     323... 
     324ValidationError: [u'This field is required.'] 
     325>>> f.clean([]) 
     326Traceback (most recent call last): 
     327... 
     328ValidationError: [u'This field is required.'] 
     329>>> f.clean([1]) 
     330[<Category: Entertainment>] 
     331>>> f.clean([2]) 
     332[<Category: It's a test>] 
     333>>> f.clean(['1']) 
     334[<Category: Entertainment>] 
     335>>> f.clean(['1', '2']) 
     336[<Category: Entertainment>, <Category: It's a test>] 
     337>>> f.clean([1, '2']) 
     338[<Category: Entertainment>, <Category: It's a test>] 
     339>>> f.clean((1, '2')) 
     340[<Category: Entertainment>, <Category: It's a test>] 
     341>>> f.clean(['nonexistent']) 
     342Traceback (most recent call last): 
     343... 
     344ValidationError: [u'Select a valid choice. nonexistent is not one of the available choices.'] 
     345>>> f.clean('hello') 
     346Traceback (most recent call last): 
     347... 
     348ValidationError: [u'Enter a list of values.'] 
     349>>> f = ModelMultipleChoiceField(Category.objects.all(), required=False) 
     350>>> f.clean([]) 
     351[] 
     352>>> f.clean(()) 
     353[] 
     354>>> f.clean(['4']) 
     355Traceback (most recent call last): 
     356... 
     357ValidationError: [u'Select a valid choice. 4 is not one of the available choices.'] 
     358>>> f.clean(['3', '4']) 
     359Traceback (most recent call last): 
     360... 
     361ValidationError: [u'Select a valid choice. 4 is not one of the available choices.'] 
     362>>> f.clean(['1', '5']) 
     363Traceback (most recent call last): 
     364... 
     365ValidationError: [u'Select a valid choice. 5 is not one of the available choices.'] 
    284366"""}