1 | '''
|
---|
2 | my_project/my_widgets.py
|
---|
3 |
|
---|
4 | '''
|
---|
5 | from django.forms import CheckboxInput, MultiWidget
|
---|
6 |
|
---|
7 |
|
---|
8 | class NullableWidget(MultiWidget):
|
---|
9 | """
|
---|
10 | A Widget that wraps another Widget and renders it along with a checkbox
|
---|
11 | that unchecked means that the value should be None (NULL) [#4136]
|
---|
12 |
|
---|
13 | """
|
---|
14 | def __init__(self, subwidget, attrs=None):
|
---|
15 | self.checkbox = CheckboxInput()
|
---|
16 | self.subwidget = subwidget
|
---|
17 | super(NullableWidget, self).__init__(
|
---|
18 | [self.checkbox, self.subwidget], attrs
|
---|
19 | )
|
---|
20 |
|
---|
21 | def decompress(self, value):
|
---|
22 | if value is None:
|
---|
23 | return [False, '']
|
---|
24 | else:
|
---|
25 | return [True, value]
|
---|
26 |
|
---|
27 | def value_from_datadict(self, data, files, name):
|
---|
28 | is_set, value = [widget.value_from_datadict(data, files, name + '_%s' % i) for i, widget in enumerate(self.widgets)]
|
---|
29 |
|
---|
30 | if is_set:
|
---|
31 | return value
|
---|
32 | else:
|
---|
33 | return None
|
---|
34 |
|
---|
35 | def _has_changed(self, initial, data):
|
---|
36 | '''
|
---|
37 | When checkbox is unticked and Text
|
---|
38 | '''
|
---|
39 | if initial is None:
|
---|
40 | initial = self.decompress(initial)
|
---|
41 | else:
|
---|
42 | if not isinstance(initial, list):
|
---|
43 | initial = self.decompress(initial)
|
---|
44 |
|
---|
45 | multi_data = self.decompress(data)
|
---|
46 | for widget, initial, data in zip(self.widgets, initial, multi_data):
|
---|
47 | if widget._has_changed(initial, data):
|
---|
48 | return True
|
---|
49 | return False
|
---|
50 |
|
---|
51 | '''
|
---|
52 | my_project/models.py
|
---|
53 |
|
---|
54 | '''
|
---|
55 | from django.db import models
|
---|
56 |
|
---|
57 | class MyModel(models.Model):
|
---|
58 | my_nullable_charfield = models.CharField("verbose name",
|
---|
59 | blank=True,
|
---|
60 | null=True,
|
---|
61 | unique=True,
|
---|
62 | default=None,
|
---|
63 | max_length=3)
|
---|
64 | '''
|
---|
65 | my_project/forms.py
|
---|
66 |
|
---|
67 | '''
|
---|
68 | from django import forms
|
---|
69 |
|
---|
70 | from my_project.models import MyModel
|
---|
71 | from my_project.my_widgets import NullableWidget
|
---|
72 |
|
---|
73 |
|
---|
74 | class MyModelForm(forms.ModelForm):
|
---|
75 | class Meta:
|
---|
76 | model = MyModel
|
---|
77 | widgets = {
|
---|
78 | "my_nullable_charfield": NullableWidget(forms.TextInput())
|
---|
79 | }
|
---|