From 16a5a2a2c8d8dbf9cc3e033dd84b986bcaadb963 Mon Sep 17 00:00:00 2001 From: Joshua Cannon Date: Fri, 4 Jan 2019 14:03:53 -0600 Subject: Fixed #30076 -- Added Model.get_FOO_display() even if field's choices are empty. --- tests/model_fields/models.py | 16 +++++++++++++ tests/model_fields/tests.py | 55 +++++++++++++++++++++++++++++++++++++++++++- 2 files changed, 70 insertions(+), 1 deletion(-) (limited to 'tests/model_fields') diff --git a/tests/model_fields/models.py b/tests/model_fields/models.py index 13d4843632..02fea36b31 100644 --- a/tests/model_fields/models.py +++ b/tests/model_fields/models.py @@ -50,6 +50,14 @@ class Whiz(models.Model): c = models.IntegerField(choices=CHOICES, null=True) +class WhizDelayed(models.Model): + c = models.IntegerField(choices=(), null=True) + + +# Contrived way of adding choices later. +WhizDelayed._meta.get_field('c').choices = Whiz.CHOICES + + class WhizIter(models.Model): c = models.IntegerField(choices=iter(Whiz.CHOICES), null=True) @@ -58,6 +66,14 @@ class WhizIterEmpty(models.Model): c = models.CharField(choices=iter(()), blank=True, max_length=1) +class Choiceful(models.Model): + no_choices = models.IntegerField(null=True) + empty_choices = models.IntegerField(choices=(), null=True) + with_choices = models.IntegerField(choices=[(1, 'A')], null=True) + empty_choices_bool = models.BooleanField(choices=()) + empty_choices_text = models.TextField(choices=()) + + class BigD(models.Model): d = models.DecimalField(max_digits=32, decimal_places=30) diff --git a/tests/model_fields/tests.py b/tests/model_fields/tests.py index 42e784db54..f55175aa9e 100644 --- a/tests/model_fields/tests.py +++ b/tests/model_fields/tests.py @@ -1,12 +1,14 @@ import pickle from django import forms +from django.core.exceptions import ValidationError from django.db import models from django.test import SimpleTestCase, TestCase from django.utils.functional import lazy from .models import ( - Bar, Foo, RenamedField, VerboseNameField, Whiz, WhizIter, WhizIterEmpty, + Bar, Choiceful, Foo, RenamedField, VerboseNameField, Whiz, WhizDelayed, + WhizIter, WhizIterEmpty, ) @@ -103,6 +105,51 @@ class BasicFieldTests(SimpleTestCase): class ChoicesTests(SimpleTestCase): + @classmethod + def setUpClass(cls): + super().setUpClass() + cls.no_choices = Choiceful._meta.get_field('no_choices') + cls.empty_choices = Choiceful._meta.get_field('empty_choices') + cls.empty_choices_bool = Choiceful._meta.get_field('empty_choices_bool') + cls.empty_choices_text = Choiceful._meta.get_field('empty_choices_text') + cls.with_choices = Choiceful._meta.get_field('with_choices') + + def test_choices(self): + self.assertIsNone(self.no_choices.choices) + self.assertEqual(self.empty_choices.choices, ()) + self.assertEqual(self.with_choices.choices, [(1, 'A')]) + + def test_flatchoices(self): + self.assertEqual(self.no_choices.flatchoices, []) + self.assertEqual(self.empty_choices.flatchoices, []) + self.assertEqual(self.with_choices.flatchoices, [(1, 'A')]) + + def test_check(self): + self.assertEqual(Choiceful.check(), []) + + def test_invalid_choice(self): + model_instance = None # Actual model instance not needed. + self.no_choices.validate(0, model_instance) + msg = "['Value 99 is not a valid choice.']" + with self.assertRaisesMessage(ValidationError, msg): + self.empty_choices.validate(99, model_instance) + with self.assertRaisesMessage(ValidationError, msg): + self.with_choices.validate(99, model_instance) + + def test_formfield(self): + no_choices_formfield = self.no_choices.formfield() + self.assertIsInstance(no_choices_formfield, forms.IntegerField) + fields = ( + self.empty_choices, self.with_choices, self.empty_choices_bool, + self.empty_choices_text, + ) + for field in fields: + with self.subTest(field=field): + self.assertIsInstance(field.formfield(), forms.ChoiceField) + + +class GetFieldDisplayTests(SimpleTestCase): + def test_choices_and_field_display(self): """ get_choices() interacts with get_FIELD_display() to return the expected @@ -113,6 +160,7 @@ class ChoicesTests(SimpleTestCase): self.assertEqual(Whiz(c=9).get_c_display(), 9) # Invalid value self.assertIsNone(Whiz(c=None).get_c_display()) # Blank value self.assertEqual(Whiz(c='').get_c_display(), '') # Empty value + self.assertEqual(WhizDelayed(c=0).get_c_display(), 'Other') # Delayed choices def test_iterator_choices(self): """ @@ -135,6 +183,11 @@ class ChoicesTests(SimpleTestCase): class GetChoicesTests(SimpleTestCase): + def test_empty_choices(self): + choices = [] + f = models.CharField(choices=choices) + self.assertEqual(f.get_choices(include_blank=False), choices) + def test_blank_in_choices(self): choices = [('', '<><>'), ('a', 'A')] f = models.CharField(choices=choices) -- cgit v1.3