mirror of
				https://github.com/django/django.git
				synced 2025-10-28 16:16:12 +00:00 
			
		
		
		
	
		
			
				
	
	
		
			159 lines
		
	
	
		
			5.5 KiB
		
	
	
	
		
			Python
		
	
	
	
	
	
			
		
		
	
	
			159 lines
		
	
	
		
			5.5 KiB
		
	
	
	
		
			Python
		
	
	
	
	
	
| from datetime import datetime
 | |
| 
 | |
| from django.forms import (
 | |
|     CharField, Form, MultipleChoiceField, MultiValueField, MultiWidget,
 | |
|     SelectMultiple, SplitDateTimeField, SplitDateTimeWidget, TextInput,
 | |
|     ValidationError,
 | |
| )
 | |
| from django.test import SimpleTestCase
 | |
| 
 | |
| beatles = (('J', 'John'), ('P', 'Paul'), ('G', 'George'), ('R', 'Ringo'))
 | |
| 
 | |
| 
 | |
| class ComplexMultiWidget(MultiWidget):
 | |
|     def __init__(self, attrs=None):
 | |
|         widgets = (
 | |
|             TextInput(),
 | |
|             SelectMultiple(choices=beatles),
 | |
|             SplitDateTimeWidget(),
 | |
|         )
 | |
|         super(ComplexMultiWidget, self).__init__(widgets, attrs)
 | |
| 
 | |
|     def decompress(self, value):
 | |
|         if value:
 | |
|             data = value.split(',')
 | |
|             return [
 | |
|                 data[0],
 | |
|                 list(data[1]),
 | |
|                 datetime.strptime(data[2], "%Y-%m-%d %H:%M:%S"),
 | |
|             ]
 | |
|         return [None, None, None]
 | |
| 
 | |
|     def format_output(self, rendered_widgets):
 | |
|         return '\n'.join(rendered_widgets)
 | |
| 
 | |
| 
 | |
| class ComplexField(MultiValueField):
 | |
|     def __init__(self, required=True, widget=None, label=None, initial=None):
 | |
|         fields = (
 | |
|             CharField(),
 | |
|             MultipleChoiceField(choices=beatles),
 | |
|             SplitDateTimeField(),
 | |
|         )
 | |
|         super(ComplexField, self).__init__(fields, required, widget, label, initial)
 | |
| 
 | |
|     def compress(self, data_list):
 | |
|         if data_list:
 | |
|             return '%s,%s,%s' % (data_list[0], ''.join(data_list[1]), data_list[2])
 | |
|         return None
 | |
| 
 | |
| 
 | |
| class ComplexFieldForm(Form):
 | |
|     field1 = ComplexField(widget=ComplexMultiWidget())
 | |
| 
 | |
| 
 | |
| class MultiValueFieldTest(SimpleTestCase):
 | |
| 
 | |
|     @classmethod
 | |
|     def setUpClass(cls):
 | |
|         cls.field = ComplexField(widget=ComplexMultiWidget())
 | |
|         super(MultiValueFieldTest, cls).setUpClass()
 | |
| 
 | |
|     def test_clean(self):
 | |
|         self.assertEqual(
 | |
|             self.field.clean(['some text', ['J', 'P'], ['2007-04-25', '6:24:00']]),
 | |
|             'some text,JP,2007-04-25 06:24:00',
 | |
|         )
 | |
| 
 | |
|     def test_bad_choice(self):
 | |
|         msg = "'Select a valid choice. X is not one of the available choices.'"
 | |
|         with self.assertRaisesMessage(ValidationError, msg):
 | |
|             self.field.clean(['some text', ['X'], ['2007-04-25', '6:24:00']])
 | |
| 
 | |
|     def test_no_value(self):
 | |
|         """
 | |
|         If insufficient data is provided, None is substituted.
 | |
|         """
 | |
|         msg = "'This field is required.'"
 | |
|         with self.assertRaisesMessage(ValidationError, msg):
 | |
|             self.field.clean(['some text', ['JP']])
 | |
| 
 | |
|     def test_has_changed_no_initial(self):
 | |
|         self.assertTrue(self.field.has_changed(None, ['some text', ['J', 'P'], ['2007-04-25', '6:24:00']]))
 | |
| 
 | |
|     def test_has_changed_same(self):
 | |
|         self.assertFalse(self.field.has_changed(
 | |
|             'some text,JP,2007-04-25 06:24:00',
 | |
|             ['some text', ['J', 'P'], ['2007-04-25', '6:24:00']],
 | |
|         ))
 | |
| 
 | |
|     def test_has_changed_first_widget(self):
 | |
|         """
 | |
|         Test when the first widget's data has changed.
 | |
|         """
 | |
|         self.assertTrue(self.field.has_changed(
 | |
|             'some text,JP,2007-04-25 06:24:00',
 | |
|             ['other text', ['J', 'P'], ['2007-04-25', '6:24:00']],
 | |
|         ))
 | |
| 
 | |
|     def test_has_changed_last_widget(self):
 | |
|         """
 | |
|         Test when the last widget's data has changed. This ensures that it is
 | |
|         not short circuiting while testing the widgets.
 | |
|         """
 | |
|         self.assertTrue(self.field.has_changed(
 | |
|             'some text,JP,2007-04-25 06:24:00',
 | |
|             ['some text', ['J', 'P'], ['2009-04-25', '11:44:00']],
 | |
|         ))
 | |
| 
 | |
|     def test_form_as_table(self):
 | |
|         form = ComplexFieldForm()
 | |
|         self.assertHTMLEqual(
 | |
|             form.as_table(),
 | |
|             """
 | |
|             <tr><th><label for="id_field1_0">Field1:</label></th>
 | |
|             <td><input type="text" name="field1_0" id="id_field1_0" required />
 | |
|             <select multiple="multiple" name="field1_1" id="id_field1_1" required>
 | |
|             <option value="J">John</option>
 | |
|             <option value="P">Paul</option>
 | |
|             <option value="G">George</option>
 | |
|             <option value="R">Ringo</option>
 | |
|             </select>
 | |
|             <input type="text" name="field1_2_0" id="id_field1_2_0" required />
 | |
|             <input type="text" name="field1_2_1" id="id_field1_2_1" required /></td></tr>
 | |
|             """,
 | |
|         )
 | |
| 
 | |
|     def test_form_as_table_data(self):
 | |
|         form = ComplexFieldForm({
 | |
|             'field1_0': 'some text',
 | |
|             'field1_1': ['J', 'P'],
 | |
|             'field1_2_0': '2007-04-25',
 | |
|             'field1_2_1': '06:24:00',
 | |
|         })
 | |
|         self.assertHTMLEqual(
 | |
|             form.as_table(),
 | |
|             """
 | |
|             <tr><th><label for="id_field1_0">Field1:</label></th>
 | |
|             <td><input type="text" name="field1_0" value="some text" id="id_field1_0" required />
 | |
|             <select multiple="multiple" name="field1_1" id="id_field1_1" required>
 | |
|             <option value="J" selected>John</option>
 | |
|             <option value="P" selected>Paul</option>
 | |
|             <option value="G">George</option>
 | |
|             <option value="R">Ringo</option>
 | |
|             </select>
 | |
|             <input type="text" name="field1_2_0" value="2007-04-25" id="id_field1_2_0" required />
 | |
|             <input type="text" name="field1_2_1" value="06:24:00" id="id_field1_2_1" required /></td></tr>
 | |
|             """,
 | |
|         )
 | |
| 
 | |
|     def test_form_cleaned_data(self):
 | |
|         form = ComplexFieldForm({
 | |
|             'field1_0': 'some text',
 | |
|             'field1_1': ['J', 'P'],
 | |
|             'field1_2_0': '2007-04-25',
 | |
|             'field1_2_1': '06:24:00',
 | |
|         })
 | |
|         form.is_valid()
 | |
|         self.assertEqual(form.cleaned_data['field1'], 'some text,JP,2007-04-25 06:24:00')
 |