2017-05-12 03:04:52 +02:00
|
|
|
import pickle
|
|
|
|
|
2016-03-22 02:06:54 +01:00
|
|
|
from django import forms
|
|
|
|
from django.db import models
|
|
|
|
from django.test import SimpleTestCase, TestCase
|
2018-04-20 16:37:29 +02:00
|
|
|
from django.utils.functional import lazy
|
2009-04-12 07:32:23 +02:00
|
|
|
|
2013-05-03 16:02:10 +02:00
|
|
|
from .models import (
|
2016-03-22 02:06:54 +01:00
|
|
|
Foo, RenamedField, VerboseNameField, Whiz, WhizIter, WhizIterEmpty,
|
2015-01-28 13:35:27 +01:00
|
|
|
)
|
2009-04-12 07:32:23 +02:00
|
|
|
|
2009-05-28 07:46:09 +02:00
|
|
|
|
2017-06-26 16:31:32 +02:00
|
|
|
class Nested:
|
2017-06-14 14:41:02 +02:00
|
|
|
class Field(models.Field):
|
|
|
|
pass
|
|
|
|
|
|
|
|
|
2016-03-22 02:06:54 +01:00
|
|
|
class BasicFieldTests(TestCase):
|
|
|
|
|
2010-03-07 02:50:58 +01:00
|
|
|
def test_show_hidden_initial(self):
|
|
|
|
"""
|
2016-03-22 02:06:54 +01:00
|
|
|
Fields with choices respect show_hidden_initial as a kwarg to
|
|
|
|
formfield().
|
2010-03-07 02:50:58 +01:00
|
|
|
"""
|
|
|
|
choices = [(0, 0), (1, 1)]
|
|
|
|
model_field = models.Field(choices=choices)
|
|
|
|
form_field = model_field.formfield(show_hidden_initial=True)
|
|
|
|
self.assertTrue(form_field.show_hidden_initial)
|
|
|
|
|
|
|
|
form_field = model_field.formfield(show_hidden_initial=False)
|
|
|
|
self.assertFalse(form_field.show_hidden_initial)
|
|
|
|
|
2011-05-03 13:51:37 +02:00
|
|
|
def test_field_repr(self):
|
|
|
|
"""
|
2016-03-22 02:06:54 +01:00
|
|
|
__repr__() of a field displays its name.
|
2011-05-03 13:51:37 +02:00
|
|
|
"""
|
|
|
|
f = Foo._meta.get_field('a')
|
|
|
|
self.assertEqual(repr(f), '<django.db.models.fields.CharField: a>')
|
|
|
|
f = models.fields.CharField()
|
|
|
|
self.assertEqual(repr(f), '<django.db.models.fields.CharField>')
|
|
|
|
|
2017-06-14 14:41:02 +02:00
|
|
|
def test_field_repr_nested(self):
|
|
|
|
"""__repr__() uses __qualname__ for nested class support."""
|
|
|
|
self.assertEqual(repr(Nested.Field()), '<model_fields.tests.Nested.Field>')
|
|
|
|
|
2011-08-13 13:53:42 +02:00
|
|
|
def test_field_name(self):
|
|
|
|
"""
|
2016-03-22 02:06:54 +01:00
|
|
|
A defined field name (name="fieldname") is used instead of the model
|
|
|
|
model's attribute name (modelname).
|
2011-08-13 13:53:42 +02:00
|
|
|
"""
|
|
|
|
instance = RenamedField()
|
|
|
|
self.assertTrue(hasattr(instance, 'get_fieldname_display'))
|
|
|
|
self.assertFalse(hasattr(instance, 'get_modelname_display'))
|
|
|
|
|
2012-09-01 18:32:27 +02:00
|
|
|
def test_field_verbose_name(self):
|
|
|
|
m = VerboseNameField
|
2016-12-31 16:30:41 +01:00
|
|
|
for i in range(1, 23):
|
2016-03-22 02:06:54 +01:00
|
|
|
self.assertEqual(m._meta.get_field('field%d' % i).verbose_name, 'verbose field%d' % i)
|
2012-09-01 18:32:27 +02:00
|
|
|
|
|
|
|
self.assertEqual(m._meta.get_field('id').verbose_name, 'verbose pk')
|
|
|
|
|
2013-08-30 05:44:37 +02:00
|
|
|
def test_choices_form_class(self):
|
2016-03-22 02:06:54 +01:00
|
|
|
"""Can supply a custom choices form class to Field.formfield()"""
|
2013-08-30 05:44:37 +02:00
|
|
|
choices = [('a', 'a')]
|
2013-02-23 19:01:38 +01:00
|
|
|
field = models.CharField(choices=choices)
|
2013-08-30 05:44:37 +02:00
|
|
|
klass = forms.TypedMultipleChoiceField
|
|
|
|
self.assertIsInstance(field.formfield(choices_form_class=klass), klass)
|
2013-02-23 19:01:38 +01:00
|
|
|
|
2017-03-22 00:29:14 +01:00
|
|
|
def test_formfield_disabled(self):
|
|
|
|
"""Field.formfield() sets disabled for fields with choices."""
|
|
|
|
field = models.CharField(choices=[('a', 'b')])
|
|
|
|
form_field = field.formfield(disabled=True)
|
|
|
|
self.assertIs(form_field.disabled, True)
|
|
|
|
|
2014-01-20 03:45:21 +01:00
|
|
|
def test_field_str(self):
|
2016-12-14 20:04:26 +01:00
|
|
|
f = models.Field()
|
|
|
|
self.assertEqual(str(f), '<django.db.models.fields.Field>')
|
2014-01-20 03:45:21 +01:00
|
|
|
f = Foo._meta.get_field('a')
|
2016-12-14 20:04:26 +01:00
|
|
|
self.assertEqual(str(f), 'model_fields.Foo.a')
|
2015-02-12 07:28:24 +01:00
|
|
|
|
2016-12-14 17:48:57 +01:00
|
|
|
def test_field_ordering(self):
|
|
|
|
"""Fields are ordered based on their creation."""
|
|
|
|
f1 = models.Field()
|
|
|
|
f2 = models.Field(auto_created=True)
|
|
|
|
f3 = models.Field()
|
|
|
|
self.assertLess(f2, f1)
|
|
|
|
self.assertGreater(f3, f1)
|
|
|
|
self.assertIsNotNone(f1)
|
|
|
|
self.assertNotIn(f2, (None, 1, ''))
|
|
|
|
|
2017-05-12 03:04:52 +02:00
|
|
|
def test_field_instance_is_picklable(self):
|
|
|
|
"""Field instances can be pickled."""
|
|
|
|
field = models.Field(max_length=100, default='a string')
|
|
|
|
# Must be picklable with this cached property populated (#28188).
|
|
|
|
field._get_default
|
|
|
|
pickle.dumps(field)
|
|
|
|
|
2017-06-14 14:41:02 +02:00
|
|
|
def test_deconstruct_nested_field(self):
|
|
|
|
"""deconstruct() uses __qualname__ for nested class support."""
|
|
|
|
name, path, args, kwargs = Nested.Field().deconstruct()
|
|
|
|
self.assertEqual(path, 'model_fields.tests.Nested.Field')
|
|
|
|
|
2016-01-10 00:05:57 +01:00
|
|
|
|
2016-03-22 02:06:54 +01:00
|
|
|
class ChoicesTests(SimpleTestCase):
|
2016-01-10 00:05:57 +01:00
|
|
|
|
2009-04-10 21:54:14 +02:00
|
|
|
def test_choices_and_field_display(self):
|
|
|
|
"""
|
2016-03-22 02:06:54 +01:00
|
|
|
get_choices() interacts with get_FIELD_display() to return the expected
|
|
|
|
values.
|
2009-04-10 21:54:14 +02:00
|
|
|
"""
|
|
|
|
self.assertEqual(Whiz(c=1).get_c_display(), 'First') # A nested value
|
|
|
|
self.assertEqual(Whiz(c=0).get_c_display(), 'Other') # A top level value
|
|
|
|
self.assertEqual(Whiz(c=9).get_c_display(), 9) # Invalid value
|
2016-06-16 20:19:18 +02:00
|
|
|
self.assertIsNone(Whiz(c=None).get_c_display()) # Blank value
|
2009-04-10 21:54:14 +02:00
|
|
|
self.assertEqual(Whiz(c='').get_c_display(), '') # Empty value
|
2009-04-12 07:32:23 +02:00
|
|
|
|
2014-07-27 23:39:40 +02:00
|
|
|
def test_iterator_choices(self):
|
|
|
|
"""
|
2016-03-22 02:06:54 +01:00
|
|
|
get_choices() works with Iterators.
|
2014-07-27 23:39:40 +02:00
|
|
|
"""
|
|
|
|
self.assertEqual(WhizIter(c=1).c, 1) # A nested value
|
|
|
|
self.assertEqual(WhizIter(c=9).c, 9) # Invalid value
|
2016-06-16 20:19:18 +02:00
|
|
|
self.assertIsNone(WhizIter(c=None).c) # Blank value
|
2014-07-27 23:39:40 +02:00
|
|
|
self.assertEqual(WhizIter(c='').c, '') # Empty value
|
|
|
|
|
|
|
|
def test_empty_iterator_choices(self):
|
|
|
|
"""
|
2016-03-22 02:06:54 +01:00
|
|
|
get_choices() works with empty iterators.
|
2014-07-27 23:39:40 +02:00
|
|
|
"""
|
|
|
|
self.assertEqual(WhizIterEmpty(c="a").c, "a") # A nested value
|
|
|
|
self.assertEqual(WhizIterEmpty(c="b").c, "b") # Invalid value
|
2016-06-16 20:19:18 +02:00
|
|
|
self.assertIsNone(WhizIterEmpty(c=None).c) # Blank value
|
2014-07-27 23:39:40 +02:00
|
|
|
self.assertEqual(WhizIterEmpty(c='').c, '') # Empty value
|
2018-04-20 16:37:29 +02:00
|
|
|
|
|
|
|
|
|
|
|
class GetChoicesTests(SimpleTestCase):
|
|
|
|
|
|
|
|
def test_blank_in_choices(self):
|
|
|
|
choices = [('', '<><>'), ('a', 'A')]
|
|
|
|
f = models.CharField(choices=choices)
|
|
|
|
self.assertEqual(f.get_choices(include_blank=True), choices)
|
|
|
|
|
|
|
|
def test_lazy_strings_not_evaluated(self):
|
|
|
|
lazy_func = lazy(lambda x: 0 / 0, int) # raises ZeroDivisionError if evaluated.
|
|
|
|
f = models.CharField(choices=[(lazy_func('group'), (('a', 'A'), ('b', 'B')))])
|
|
|
|
self.assertEqual(f.get_choices(include_blank=True)[0], ('', '---------'))
|