У меня есть модельный набор форм, настроенный с использованием Django Dynami c Formset вместе с Хрустящими формами и библиотекой Datepicker Tempus Dominus . Это простой набор форм для пользователей, позволяющий добавлять записи строки операционных расходов - дату, категорию, описание и сумму.
Мой указатель даты работает правильно с не динамическим c формой. Однако при использовании динамических c форм и добавлении новой формы виджет в конечном итоге нацеливается на последнюю форму в наборе форм, из которой он был клонирован, а не на текущую форму (https://imgur.com/a/2GFYZ90). Вместо правильного приращения (т. Е. Form_3, form_4, form_5 и т. Д. c.), Оно просто ссылается на последнюю форму набора форм (т. Е. Form_2) перед добавлением новых. В результате, если я пытаюсь переключать средства выбора даты в любой из динамически добавляемых форм, он просто запускает тот, что находится в form_2. Обычные текстовые поля клонируются правильно без каких-либо проблем.
Как вы можете видеть в строках 19-23 opex. html, я пытаюсь реализовать функции уничтожения и повторной инициализации, как предлагалось некоторыми старыми стеками. Сообщения переполнения ( 1 , 2 и 3 ), но я нуб JS, поэтому я не уверен, что делать дальше.
models.py
class OpEx(models.Model):
GEN_EXP = 'GE'
OFFICE_SUP = 'OS'
NR_EXP = 'NR'
CATEGORY_CHOICES = [
(GEN_EXP, 'General Expenses'),
(OFFICE_SUP, 'Office Supplies'),
(NR_EXP, 'Non-Recurring Expenses'),
]
exp_user = models.ForeignKey(settings.AUTH_USER_MODEL, on_delete=models.CASCADE, default=0)
exp_date = models.DateField(verbose_name='Date')
category = models.CharField(max_length=2, choices=CATEGORY_CHOICES, default=GEN_EXP)
description = models.CharField(max_length=255)
amount = models.DecimalField(verbose_name='Amount ($)', max_digits=10, decimal_places=2)
forms.py
class OpExEntryForm(ModelForm):
class Meta:
model = OpEx
exclude = ('id', 'exp_user')
class OpExFormSetHelper(FormHelper):
def __init__(self, *args, **kwargs):
super(OpExFormSetHelper, self).__init__(*args, **kwargs)
self.form_method = 'POST'
self.form_class = 'form-inline'
self.form_show_labels = False
self.layout = Layout(
Row(
Column('exp_date', css_class='col-sm-2'),
Column('category', css_class='col-sm-3'),
Column('description', css_class='col-sm-4'),
Column(PrependedText('amount', "<span class='fa fa-dollar-sign'"), css_class='col-sm-2'),
css_class='opex-formset-row'
)
)
self.render_required_fields = True
self.add_input(Submit('submit', 'Update operating expenses'))
views.py
def opex(request):
OpExFormSet = modelformset_factory(OpEx, exclude=('id', 'exp_user'),
widgets={'exp_date': DatePicker(attrs={'append': 'fa fa-calendar'})},
form=OpExEntryForm, extra=0, can_delete=True)
helper = OpExFormSetHelper()
queryset = OpEx.objects.filter(exp_user=user)
if request.method == 'POST':
formset = OpExFormSet(request.POST, queryset=queryset)
# Irrelevant code...
else:
formset = OpExFormSet(queryset=queryset)
return render(request, 'opex.html', {'formset': formset, 'helper': helper})
opex. html
{% extends 'base.html' %}
{% load crispy_forms_tags %}
{% load static %}
{% block extra_head %}
{{ form.media }}
{% endblock %}
{% block content %}
{% crispy formset helper %}
<!-- Load Django Dynamic Formset -->
<script type="text/javascript" src="{% static 'js/jquery.formset.js' %}"></script>
<script type="text/javascript">
$(function() {
$('.opex-formset-row').formset({
addText : 'add another',
deleteText : 'remove',
added: function (row) {
var datePicker = $(row).find('input[name$="exp_date"]');
if (datePicker.length > 0) {
datePicker.datetimepicker('destroy');
}
}
});
})
</script>
{% endblock %}