test_multivaluefield.py 5.6 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158
  1. from datetime import datetime
  2. from django.forms import (
  3. CharField, Form, MultipleChoiceField, MultiValueField, MultiWidget,
  4. SelectMultiple, SplitDateTimeField, SplitDateTimeWidget, TextInput,
  5. ValidationError,
  6. )
  7. from django.test import SimpleTestCase
  8. beatles = (('J', 'John'), ('P', 'Paul'), ('G', 'George'), ('R', 'Ringo'))
  9. class ComplexMultiWidget(MultiWidget):
  10. def __init__(self, attrs=None):
  11. widgets = (
  12. TextInput(),
  13. SelectMultiple(choices=beatles),
  14. SplitDateTimeWidget(),
  15. )
  16. super(ComplexMultiWidget, self).__init__(widgets, attrs)
  17. def decompress(self, value):
  18. if value:
  19. data = value.split(',')
  20. return [
  21. data[0],
  22. list(data[1]),
  23. datetime.strptime(data[2], "%Y-%m-%d %H:%M:%S"),
  24. ]
  25. return [None, None, None]
  26. def format_output(self, rendered_widgets):
  27. return '\n'.join(rendered_widgets)
  28. class ComplexField(MultiValueField):
  29. def __init__(self, required=True, widget=None, label=None, initial=None):
  30. fields = (
  31. CharField(),
  32. MultipleChoiceField(choices=beatles),
  33. SplitDateTimeField(),
  34. )
  35. super(ComplexField, self).__init__(fields, required, widget, label, initial)
  36. def compress(self, data_list):
  37. if data_list:
  38. return '%s,%s,%s' % (data_list[0], ''.join(data_list[1]), data_list[2])
  39. return None
  40. class ComplexFieldForm(Form):
  41. field1 = ComplexField(widget=ComplexMultiWidget())
  42. class MultiValueFieldTest(SimpleTestCase):
  43. @classmethod
  44. def setUpClass(cls):
  45. cls.field = ComplexField(widget=ComplexMultiWidget())
  46. super(MultiValueFieldTest, cls).setUpClass()
  47. def test_clean(self):
  48. self.assertEqual(
  49. self.field.clean(['some text', ['J', 'P'], ['2007-04-25', '6:24:00']]),
  50. 'some text,JP,2007-04-25 06:24:00',
  51. )
  52. def test_bad_choice(self):
  53. msg = "'Select a valid choice. X is not one of the available choices.'"
  54. with self.assertRaisesMessage(ValidationError, msg):
  55. self.field.clean(['some text', ['X'], ['2007-04-25', '6:24:00']])
  56. def test_no_value(self):
  57. """
  58. If insufficient data is provided, None is substituted.
  59. """
  60. msg = "'This field is required.'"
  61. with self.assertRaisesMessage(ValidationError, msg):
  62. self.field.clean(['some text', ['JP']])
  63. def test_has_changed_no_initial(self):
  64. self.assertTrue(self.field.has_changed(None, ['some text', ['J', 'P'], ['2007-04-25', '6:24:00']]))
  65. def test_has_changed_same(self):
  66. self.assertFalse(self.field.has_changed(
  67. 'some text,JP,2007-04-25 06:24:00',
  68. ['some text', ['J', 'P'], ['2007-04-25', '6:24:00']],
  69. ))
  70. def test_has_changed_first_widget(self):
  71. """
  72. Test when the first widget's data has changed.
  73. """
  74. self.assertTrue(self.field.has_changed(
  75. 'some text,JP,2007-04-25 06:24:00',
  76. ['other text', ['J', 'P'], ['2007-04-25', '6:24:00']],
  77. ))
  78. def test_has_changed_last_widget(self):
  79. """
  80. Test when the last widget's data has changed. This ensures that it is
  81. not short circuiting while testing the widgets.
  82. """
  83. self.assertTrue(self.field.has_changed(
  84. 'some text,JP,2007-04-25 06:24:00',
  85. ['some text', ['J', 'P'], ['2009-04-25', '11:44:00']],
  86. ))
  87. def test_form_as_table(self):
  88. form = ComplexFieldForm()
  89. self.assertHTMLEqual(
  90. form.as_table(),
  91. """
  92. <tr><th><label for="id_field1_0">Field1:</label></th>
  93. <td><input type="text" name="field1_0" id="id_field1_0" required />
  94. <select multiple="multiple" name="field1_1" id="id_field1_1" required>
  95. <option value="J">John</option>
  96. <option value="P">Paul</option>
  97. <option value="G">George</option>
  98. <option value="R">Ringo</option>
  99. </select>
  100. <input type="text" name="field1_2_0" id="id_field1_2_0" required />
  101. <input type="text" name="field1_2_1" id="id_field1_2_1" required /></td></tr>
  102. """,
  103. )
  104. def test_form_as_table_data(self):
  105. form = ComplexFieldForm({
  106. 'field1_0': 'some text',
  107. 'field1_1': ['J', 'P'],
  108. 'field1_2_0': '2007-04-25',
  109. 'field1_2_1': '06:24:00',
  110. })
  111. self.assertHTMLEqual(
  112. form.as_table(),
  113. """
  114. <tr><th><label for="id_field1_0">Field1:</label></th>
  115. <td><input type="text" name="field1_0" value="some text" id="id_field1_0" required />
  116. <select multiple="multiple" name="field1_1" id="id_field1_1" required>
  117. <option value="J" selected="selected">John</option>
  118. <option value="P" selected="selected">Paul</option>
  119. <option value="G">George</option>
  120. <option value="R">Ringo</option>
  121. </select>
  122. <input type="text" name="field1_2_0" value="2007-04-25" id="id_field1_2_0" required />
  123. <input type="text" name="field1_2_1" value="06:24:00" id="id_field1_2_1" required /></td></tr>
  124. """,
  125. )
  126. def test_form_cleaned_data(self):
  127. form = ComplexFieldForm({
  128. 'field1_0': 'some text',
  129. 'field1_1': ['J', 'P'],
  130. 'field1_2_0': '2007-04-25',
  131. 'field1_2_1': '06:24:00',
  132. })
  133. form.is_valid()
  134. self.assertEqual(form.cleaned_data['field1'], 'some text,JP,2007-04-25 06:24:00')