Ticket #9245: issue9245-alt.diff

File issue9245-alt.diff, 10.1 KB (added by ambv, 3 years ago)

An alternative patch which puts the responsibility of handling overrides on model fields

  • django/trunk/tests/regressiontests/model_fields/tests.py

    diff --git a/django/trunk/tests/regressiontests/model_fields/tests.py b/django/trunk/tests/regressiontests/model_fields/tests.py
    a b  
    1111from django.utils import unittest
    1212
    1313from .models import (Foo, Bar, Whiz, BigD, BigS, Image, BigInt, Post,
    14     NullBooleanModel, BooleanModel, Document, RenamedField)
     14    NullBooleanModel, BooleanModel, Document, RenamedField,
     15    CustomIntegerFormField)
    1516
    1617# If PIL available, do these tests.
    1718if Image:
     
    223224        self.assertEqual(Whiz(c=None).get_c_display(), None)    # Blank value
    224225        self.assertEqual(Whiz(c='').get_c_display(), '')        # Empty value
    225226
     227    def test_choices_formfield_overrides(self):
     228        whiz_meta = Whiz(c=1)._meta
     229        field = whiz_meta.get_field_by_name('c')[0]
     230        self.assertIs(type(field.formfield()),
     231                forms.TypedChoiceField)
     232        self.assertIs(type(whiz_meta.get_field_by_name('d')[0].formfield()),
     233                CustomIntegerFormField)
     234        self.assertIs(type(whiz_meta.get_field_by_name('ts')[0].formfield()),
     235                forms.DateTimeField)
     236
    226237class SlugFieldTests(test.TestCase):
    227238    def test_slugfield_max_length(self):
    228239        """
  • django/trunk/tests/regressiontests/model_fields/models.py

    diff --git a/django/trunk/tests/regressiontests/model_fields/models.py b/django/trunk/tests/regressiontests/model_fields/models.py
    a b  
    1313    except ImportError:
    1414        Image = None
    1515
     16from django import forms
    1617from django.core.files.storage import FileSystemStorage
    1718from django.db import models
    1819from django.db.models.fields.files import ImageFieldFile, ImageField
     
    2930    b = models.CharField(max_length=10)
    3031    a = models.ForeignKey(Foo, default=get_foo)
    3132
     33class CustomIntegerFormField(forms.IntegerField):
     34    def __init__(self, *args, **kwargs):
     35        if 'choices' in kwargs:
     36            del kwargs['choices']
     37        super(CustomIntegerFormField, self).__init__(*args, **kwargs)
     38
     39class CustomIntegerField(models.IntegerField):
     40    def formfield(self, **kwargs):
     41        if 'form_class' not in kwargs:
     42            kwargs['form_class'] = CustomIntegerFormField
     43        return super(CustomIntegerField, self).formfield(**kwargs)
     44
    3245class Whiz(models.Model):
    3346    CHOICES = (
    3447        ('Group 1', (
     
    4457        (0,'Other'),
    4558    )
    4659    c = models.IntegerField(choices=CHOICES, null=True)
     60    d = CustomIntegerField(choices=CHOICES, default=4)
     61    ts = models.DateTimeField(auto_now_add=True)
    4762
    4863class BigD(models.Model):
    4964    d = models.DecimalField(max_digits=38, decimal_places=30)
  • django/trunk/django/db/models/fields/__init__.py

    diff --git a/django/trunk/django/db/models/fields/__init__.py b/django/trunk/django/db/models/fields/__init__.py
    a b  
    453453    def save_form_data(self, instance, data):
    454454        setattr(instance, self.name, data)
    455455
    456     def formfield(self, form_class=forms.CharField, **kwargs):
     456    def formfield(self, form_class=None, **kwargs):
    457457        """
    458458        Returns a django.forms.Field instance for this database Field.
    459459        """
     
    471471            include_blank = (self.blank or
    472472                             not (self.has_default() or 'initial' in kwargs))
    473473            defaults['choices'] = self.get_choices(include_blank=include_blank)
    474             defaults['coerce'] = self.to_python
    475             if self.null:
    476                 defaults['empty_value'] = None
    477             form_class = forms.TypedChoiceField
    478             # Many of the subclass-specific formfield arguments (min_value,
    479             # max_value) don't apply for choice fields, so be sure to only pass
    480             # the values that TypedChoiceField will understand.
    481             for k in kwargs.keys():
    482                 if k not in ('coerce', 'empty_value', 'choices', 'required',
    483                              'widget', 'label', 'initial', 'help_text',
    484                              'error_messages', 'show_hidden_initial'):
    485                     del kwargs[k]
     474            if not form_class:
     475                form_class = forms.TypedChoiceField
     476                defaults['coerce'] = self.to_python
     477                if self.null:
     478                    defaults['empty_value'] = None
     479                # Many of the subclass-specific formfield arguments (min_value,
     480                # max_value) don't apply for choice fields, so be sure to only
     481                # pass the values that TypedChoiceField will understand.
     482                for k in kwargs.keys():
     483                    if k not in ('coerce', 'empty_value', 'choices', 'required',
     484                                'widget', 'label', 'initial', 'help_text',
     485                                'error_messages', 'show_hidden_initial'):
     486                        del kwargs[k]
     487        if not form_class:
     488            form_class = forms.CharField
    486489        defaults.update(kwargs)
    487490        return form_class(**defaults)
    488491
     
    722725        return '' if val is None else val.isoformat()
    723726
    724727    def formfield(self, **kwargs):
    725         defaults = {'form_class': forms.DateField}
    726         defaults.update(kwargs)
     728        if self.choices:
     729            defaults = kwargs
     730        else:
     731            defaults = {'form_class': forms.DateField}
     732            defaults.update(kwargs)
    727733        return super(DateField, self).formfield(**defaults)
    728734
    729735class DateTimeField(DateField):
     
    821827        return '' if val is None else val.isoformat()
    822828
    823829    def formfield(self, **kwargs):
    824         defaults = {'form_class': forms.DateTimeField}
    825         defaults.update(kwargs)
     830        if self.choices:
     831            defaults = kwargs
     832        else:
     833            defaults = {'form_class': forms.DateTimeField}
     834            defaults.update(kwargs)
    826835        return super(DateTimeField, self).formfield(**defaults)
    827836
    828837class DecimalField(Field):
     
    949958            raise exceptions.ValidationError(msg)
    950959
    951960    def formfield(self, **kwargs):
    952         defaults = {'form_class': forms.FloatField}
    953         defaults.update(kwargs)
     961        if self.choices:
     962            defaults = kwargs
     963        else:
     964            defaults = {'form_class': forms.FloatField}
     965            defaults.update(kwargs)
    954966        return super(FloatField, self).formfield(**defaults)
    955967
    956968class IntegerField(Field):
     
    984996            raise exceptions.ValidationError(msg)
    985997
    986998    def formfield(self, **kwargs):
    987         defaults = {'form_class': forms.IntegerField}
    988         defaults.update(kwargs)
     999        if self.choices:
     1000            defaults = kwargs
     1001        else:
     1002            defaults = {'form_class': forms.IntegerField}
     1003            defaults.update(kwargs)
    9891004        return super(IntegerField, self).formfield(**defaults)
    9901005
    9911006class BigIntegerField(IntegerField):
     
    10141029        return "IPAddressField"
    10151030
    10161031    def formfield(self, **kwargs):
    1017         defaults = {'form_class': forms.IPAddressField}
    1018         defaults.update(kwargs)
     1032        if self.choices:
     1033            defaults = kwargs
     1034        else:
     1035            defaults = {'form_class': forms.IPAddressField}
     1036            defaults.update(kwargs)
    10191037        return super(IPAddressField, self).formfield(**defaults)
    10201038
    10211039class GenericIPAddressField(Field):
     
    10541072        return value
    10551073
    10561074    def formfield(self, **kwargs):
    1057         defaults = {'form_class': forms.GenericIPAddressField}
    1058         defaults.update(kwargs)
     1075        if self.choices:
     1076            defaults = kwargs
     1077        else:
     1078            defaults = {'form_class': forms.GenericIPAddressField}
     1079            defaults.update(kwargs)
    10591080        return super(GenericIPAddressField, self).formfield(**defaults)
    10601081
    1061 
    10621082class NullBooleanField(Field):
    10631083    empty_strings_allowed = False
    10641084    default_error_messages = {
     
    11051125
    11061126    def formfield(self, **kwargs):
    11071127        defaults = {
    1108             'form_class': forms.NullBooleanField,
    11091128            'required': not self.blank,
    11101129            'label': capfirst(self.verbose_name),
    11111130            'help_text': self.help_text}
    11121131        defaults.update(kwargs)
     1132        if not self.choices:
     1133            defaults['form_class'] = forms.NullBooleanField
    11131134        return super(NullBooleanField, self).formfield(**defaults)
    11141135
    11151136class PositiveIntegerField(IntegerField):
     
    11481169        return "SlugField"
    11491170
    11501171    def formfield(self, **kwargs):
    1151         defaults = {'form_class': forms.SlugField}
     1172        if self.choices:
     1173            defaults = kwargs
     1174        else:
     1175            defaults = {'form_class': forms.SlugField}
     1176            defaults.update(kwargs)
    11521177        defaults.update(kwargs)
    11531178        return super(SlugField, self).formfield(**defaults)
    11541179
     
    12411266        return '' if val is None else val.isoformat()
    12421267
    12431268    def formfield(self, **kwargs):
    1244         defaults = {'form_class': forms.TimeField}
    1245         defaults.update(kwargs)
     1269        if self.choices:
     1270            defaults = kwargs
     1271        else:
     1272            defaults = {'form_class': forms.TimeField}
     1273            defaults.update(kwargs)
    12461274        return super(TimeField, self).formfield(**defaults)
    12471275
    12481276class URLField(CharField):
     
    12581286    def formfield(self, **kwargs):
    12591287        # As with CharField, this will cause URL validation to be performed
    12601288        # twice.
    1261         defaults = {
    1262             'form_class': forms.URLField,
    1263         }
    1264         defaults.update(kwargs)
     1289        if self.choices:
     1290            defaults = kwargs
     1291        else:
     1292            defaults = {'form_class': forms.URLField}
     1293            defaults.update(kwargs)
    12651294        return super(URLField, self).formfield(**defaults)
Back to Top