Adding BLANK_CHOICE_DASH as a choice if the model's field isn't required

This commit is contained in:
Pablo Recio 2013-05-18 12:40:25 +02:00
parent de5cc8de42
commit ab8bd566f9
4 changed files with 100 additions and 2 deletions

View File

@ -15,6 +15,7 @@ import warnings
from django.core import validators from django.core import validators
from django.core.exceptions import ValidationError from django.core.exceptions import ValidationError
from django.conf import settings from django.conf import settings
from django.db.models.fields import BLANK_CHOICE_DASH
from django import forms from django import forms
from django.forms import widgets from django.forms import widgets
from django.utils.encoding import is_protected_type from django.utils.encoding import is_protected_type
@ -402,6 +403,8 @@ class ChoiceField(WritableField):
def __init__(self, choices=(), *args, **kwargs): def __init__(self, choices=(), *args, **kwargs):
super(ChoiceField, self).__init__(*args, **kwargs) super(ChoiceField, self).__init__(*args, **kwargs)
self.choices = choices self.choices = choices
if not self.required:
self.choices = BLANK_CHOICE_DASH + self.choices
def _get_choices(self): def _get_choices(self):
return self._choices return self._choices

View File

@ -645,4 +645,30 @@ class DecimalFieldTest(TestCase):
s = DecimalSerializer(data={'decimal_field': '12345.6'}) s = DecimalSerializer(data={'decimal_field': '12345.6'})
self.assertFalse(s.is_valid()) self.assertFalse(s.is_valid())
self.assertEqual(s.errors, {'decimal_field': ['Ensure that there are no more than 4 digits in total.']}) self.assertEqual(s.errors, {'decimal_field': ['Ensure that there are no more than 4 digits in total.']})
class ChoiceFieldTests(TestCase):
"""
Tests for the ChoiceField options generator
"""
SAMPLE_CHOICES = [
('red', 'Red'),
('green', 'Green'),
('blue', 'Blue'),
]
def test_choices_required(self):
"""
Make sure proper choices are rendered if field is required
"""
f = serializers.ChoiceField(required=True, choices=self.SAMPLE_CHOICES)
self.assertEqual(f.choices, self.SAMPLE_CHOICES)
def test_choices_not_required(self):
"""
Make sure proper choices (plus blank) are rendered if the field isn't required
"""
f = serializers.ChoiceField(required=False, choices=self.SAMPLE_CHOICES)
self.assertEqual(f.choices, models.fields.BLANK_CHOICE_DASH + self.SAMPLE_CHOICES)

View File

@ -117,6 +117,32 @@ class OptionalRelationModel(RESTFrameworkModel):
other = models.ForeignKey('OptionalRelationModel', blank=True, null=True) other = models.ForeignKey('OptionalRelationModel', blank=True, null=True)
# Model for issue #725
class SeveralChoicesModel(RESTFrameworkModel):
color = models.CharField(
max_length=10,
choices=[('red', 'Red'), ('green', 'Green'), ('blue', 'Blue')],
blank=False
)
drink = models.CharField(
max_length=10,
choices=[('beer', 'Beer'), ('wine', 'Wine'), ('cider', 'Cider')],
blank=False,
default='beer'
)
os = models.CharField(
max_length=10,
choices=[('linux', 'Linux'), ('osx', 'OSX'), ('windows', 'Windows')],
blank=True
)
music_genre = models.CharField(
max_length=10,
choices=[('rock', 'Rock'), ('metal', 'Metal'), ('grunge', 'Grunge')],
blank=True,
default='metal'
)
# Model for RegexField # Model for RegexField
class Book(RESTFrameworkModel): class Book(RESTFrameworkModel):
isbn = models.CharField(max_length=13) isbn = models.CharField(max_length=13)

View File

@ -1,10 +1,11 @@
from __future__ import unicode_literals from __future__ import unicode_literals
from django.db.models.fields import BLANK_CHOICE_DASH
from django.utils.datastructures import MultiValueDict from django.utils.datastructures import MultiValueDict
from django.test import TestCase from django.test import TestCase
from rest_framework import serializers from rest_framework import serializers
from rest_framework.tests.models import (HasPositiveIntegerAsChoice, Album, ActionItem, Anchor, BasicModel, from rest_framework.tests.models import (HasPositiveIntegerAsChoice, Album, ActionItem, Anchor, BasicModel,
BlankFieldModel, BlogPost, BlogPostComment, Book, CallableDefaultValueModel, DefaultValueModel, BlankFieldModel, BlogPost, BlogPostComment, Book, CallableDefaultValueModel, DefaultValueModel,
ManyToManyModel, Person, ReadOnlyManyToManyModel, Photo) ManyToManyModel, Person, ReadOnlyManyToManyModel, Photo, SeveralChoicesModel)
import datetime import datetime
import pickle import pickle
@ -1018,6 +1019,48 @@ class SerializerPickleTests(TestCase):
repr(pickle.loads(pickle.dumps(data, 0))) repr(pickle.loads(pickle.dumps(data, 0)))
# test for issue #725
class SerializerChoiceFields(TestCase):
def setUp(self):
super(SerializerChoiceFields, self).setUp()
class SeveralChoicesSerializer(serializers.ModelSerializer):
class Meta:
model = SeveralChoicesModel
fields = ('color', 'drink', 'os', 'music_genre')
self.several_choices_serializer = SeveralChoicesSerializer
def test_choices_blank_false_not_default(self):
serializer = self.several_choices_serializer()
self.assertEqual(
serializer.fields['color'].choices,
[('red', 'Red'), ('green', 'Green'), ('blue', 'Blue')]
)
def test_choices_blank_false_with_default(self):
serializer = self.several_choices_serializer()
self.assertEqual(
serializer.fields['drink'].choices,
[('beer', 'Beer'), ('wine', 'Wine'), ('cider', 'Cider')]
)
def test_choices_blank_true_not_default(self):
serializer = self.several_choices_serializer()
self.assertEqual(
serializer.fields['os'].choices,
BLANK_CHOICE_DASH + [('linux', 'Linux'), ('osx', 'OSX'), ('windows', 'Windows')]
)
def test_choices_blank_true_with_default(self):
serializer = self.several_choices_serializer()
self.assertEqual(
serializer.fields['music_genre'].choices,
BLANK_CHOICE_DASH + [('rock', 'Rock'), ('metal', 'Metal'), ('grunge', 'Grunge')]
)
class DepthTest(TestCase): class DepthTest(TestCase):
def test_implicit_nesting(self): def test_implicit_nesting(self):