Ticket #3257: related_choice_fields_moved_trunk_resync.patch

File related_choice_fields_moved_trunk_resync.patch, 7.6 KB (added by kilian.cavalotti@…, 13 years ago)

Resynch'ed patch against trunk rev [4451]

  • django/db/models/fields/related.py

     
    553553        setattr(cls, related.get_accessor_name(), ForeignRelatedObjectsDescriptor(related))
    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):
    561561    def __init__(self, to, to_field=None, **kwargs):
     
    619619            cls._meta.one_to_one_field = self
    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):
    627627    def __init__(self, to, **kwargs):
     
    742742        # MultipleChoiceField takes a list of IDs.
    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):
    750750    def __init__(self, to, field_name, num_in_admin=3, min_num_in_admin=None,
  • django/newforms/models.py

     
    44"""
    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):
    1114    """
     
    3336    for f in opts.fields:
    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()
    3942        for f in opts.many_to_many:
     
    9699    "Returns a Form class for the given list of Django database field instances."
    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    def __init__(self, queryset, **kwargs ):
     105        self.model = queryset.model
     106        ChoiceField.__init__(self, choices=[(obj._get_pk_val(), str(obj)) for obj in queryset], **kwargs)
     107 
     108    def clean(self, value):
     109        new_value = ChoiceField.clean(self, value)
     110        if not new_value:
     111            return None
     112        try:
     113            new_value = self.model._default_manager.get(pk=new_value)
     114        except:
     115            raise ValidationError(gettext(u'Select a valid choice. %s is not one of the available choices.') % value)
     116        return new_value
     117 
     118class ModelMultipleChoiceField(MultipleChoiceField):
     119    def __init__(self, queryset, **kwargs ):
     120        self.model = queryset.model
     121        MultipleChoiceField.__init__(self, choices=[(obj._get_pk_val(), str(obj)) for obj in queryset], **kwargs)
     122 
     123    def clean(self, value):
     124        new_value = MultipleChoiceField.clean(self, value)
     125        if not new_value:
     126            return []
     127        return self.model._default_manager.filter(pk__in=new_value) 
  • tests/modeltests/model_forms/models.py

     
    2424
    2525from django.db import models
    2626
     27class Poll(models.Model):
     28    question = models.CharField(maxlength=200)
     29    def __str__(self):
     30        return "Q: %s " % self.question
     31
    2732class Category(models.Model):
    2833    name = models.CharField(maxlength=20)
    2934    url = models.CharField('The URL', maxlength=40)
     
    282287>>> Category.objects.get(id=3)
    283288<Category: Third>
    284289"""}
     290
     291# ModelChoiceField #################################################################
     292
     293>>> from django.newforms import *
     294
     295>>> p = Poll(question="Test Question")
     296>>> p.save()
     297>>> p2 = Poll(question="Second Test Question")
     298>>> p2.save()
     299
     300>>> f = ModelChoiceField(Poll.objects.all())
     301>>> f.clean('')
     302Traceback (most recent call last):
     303...
     304ValidationError: [u'This field is required.']
     305>>> f.clean(None)
     306Traceback (most recent call last):
     307...
     308ValidationError: [u'This field is required.']
     309>>> f.clean(0)
     310Traceback (most recent call last):
     311...
     312ValidationError: [u'Select a valid choice. 0 is not one of the available choices.']
     313>>> f.clean(1)
     314<Poll: Q: Test Question >
     315>>> f.clean(2)
     316<Poll: Q: Second Test Question >
     317
     318>>> f = ModelChoiceField(Poll.objects.filter( pk=1 ), required=False)
     319>>> print f.clean('')
     320None
     321>>> f.clean('')
     322>>> f.clean('1')
     323<Poll: Q: Test Question >
     324>>> f.clean('2')
     325Traceback (most recent call last):
     326...
     327ValidationError: [u'Select a valid choice. 2 is not one of the available choices.']
     328
     329# ModelMultipleChoiceField #########################################################
     330
     331>>> f = ModelMultipleChoiceField(Poll.objects.all())
     332>>> f.clean(None)
     333Traceback (most recent call last):
     334...
     335ValidationError: [u'This field is required.']
     336>>> f.clean([])
     337Traceback (most recent call last):
     338...
     339ValidationError: [u'This field is required.']
     340>>> f.clean([1])
     341[<Poll: Q: Test Question >]
     342>>> f.clean([2])
     343[<Poll: Q: Second Test Question >]
     344>>> f.clean(['1'])
     345[<Poll: Q: Test Question >]
     346>>> f.clean(['1', '2'])
     347[<Poll: Q: Test Question >, <Poll: Q: Second Test Question >]
     348>>> f.clean([1, '2'])
     349[<Poll: Q: Test Question >, <Poll: Q: Second Test Question >]
     350>>> f.clean((1, '2'))
     351[<Poll: Q: Test Question >, <Poll: Q: Second Test Question >]
     352>>> f.clean('hello')
     353Traceback (most recent call last):
     354...
     355ValidationError: [u'Enter a list of values.']
     356>>> f = ModelMultipleChoiceField(Poll.objects.all(), required=False)
     357>>> f.clean([])
     358[]
     359>>> f.clean(())
     360[]
     361>>> f.clean(['3'])
     362Traceback (most recent call last):
     363...
     364ValidationError: [u'Select a valid choice. 3 is not one of the available choices.']
     365>>> f.clean(['3', '4'])
     366Traceback (most recent call last):
     367...
     368ValidationError: [u'Select a valid choice. 3 is not one of the available choices.']
     369>>> f.clean(['1', '5'])
     370Traceback (most recent call last):
     371...
     372ValidationError: [u'Select a valid choice. 5 is not one of the available choices.']
     373"""}
Back to Top