Я создал простой пользовательский MultiValueField
и MultiWidget
с целью ввода даты рождения, но с возможностью отдельного ввода дня, месяца и года.Смысл в том, что приложение предназначено для ввода исторических данных, поэтому одно или несколько из этих полей могут быть неизвестны.Существует также флажок, который отображает «неизвестный» на сайте, обращенном к пользователю.
Я обнаружил, что все работает нормально, за исключением того, что когда я сохраняю экземпляр объекта на сайте администратора и перехожу к созданиюВ новом экземпляре в пустой форме администратора отображаются значения даты из предыдущей записи:
![Custom MultiWidget](https://i.stack.imgur.com/QBejq.png)
Все эти поля должны быть пустыми для новой записи.
Похоже, что поле не инициализируется правильно, но я не уверен, где это должно происходить.Я добавил обходной путь, проверив в форме, нужно ли повторно инициализировать поля, но я чувствую, что это следует сделать в настраиваемом поле / виджете.
Пример кода:
class CustomDateWidget(forms.MultiWidget):
"""Custom MultiWidget to allow saving different date values."""
template_name = 'myapp/widgets/custom_date_widget.html'
def __init__(self, attrs=None):
_widgets = (forms.NumberInput(attrs=({'placeholder': 'DD'})),
forms.NumberInput(attrs=({'placeholder': 'MM'})),
forms.NumberInput(attrs=({'placeholder': 'YYYY'})),
forms.CheckboxInput())
super().__init__(_widgets, attrs)
def decompress(self, value):
if value:
return value
else:
return '', '', '', False
def value_from_datadict(self, data, files, name):
value_list = [
widget.value_from_datadict(data, files, name + '_%s' % i)
for i, widget in enumerate(self.widgets)
]
return value_list
class CustomDateField(forms.MultiValueField):
"""Custom MultiValueField to allow saving different date values."""
def __init__(self, **kwargs):
fields = (forms.IntegerField(min_value=1, max_value=31), forms.IntegerField(min_value=1, max_value=12),
forms.IntegerField(min_value=1800, max_value=9999), forms.BooleanField())
super().__init__(fields=fields, widget=CustomDateWidget, require_all_fields=True,
**kwargs)
def compress(self, data_list):
return data_list
class PersonAdminForm(forms.ModelForm):
"""Custom Person admin form."""
date_of_birth = CustomDateField(required=False)
class Meta:
model = Person
fields = '__all__'
def __init__(self, *args, **kwargs):
super(PersonAdminForm, self).__init__(*args, **kwargs)
# Dirty workaround?
if not self.instance.pk:
self.fields['date_of_birth'] = CustomDateField(required=False)
...
Виджетшаблон:
<style>
.custom-date-widget-container {
padding-right: 15px;
}
.custom-date-widget td {
width: 25%;
}
.custom-date-widget td > input {
width: 100%;
box-sizing: border-box;
}
</style>
{% spaceless %}
<div class="custom-date-widget-container">
<table class="custom-date-widget">
<thead>
<tr>
<th>Day</th>
<th>Month</th>
<th>Year</th>
<th>Unknown</th>
</tr>
</thead>
<tbody>
<tr>
{% for widget in widget.subwidgets %}
<td>{% include widget.template_name %}</td>
{% endfor %}
</tr>
</tbody>
</table>
</div>
{% endspaceless %}