我有一个使用Django Dynamic Formset以及Crispy Forms和Tempus Dominus datepicker 库设置的模型表单集。这是一个简单的表单集,供用户添加运营费用行条目——日期、类别、描述和金额。
我的日期选择器可以与非动态表单集一起正常工作。但是,当使用动态表单集并添加新表单时,小部件最终会定位到从中克隆它的表单集中的最后一个表单,而不是当前表单 ( https://imgur.com/a/2GFYZ90 )。它不是正确递增(即 form_3、form_4、form_5 等),而是指在添加新表单之前的最后一个表单(即 form_2)。因此,如果我尝试在任何动态添加的表单中切换日期选择器,它只会触发 form_2 中的那个。常规文本字段可以正确克隆,没有任何问题。
正如您在 opex.html 的第 19-23 行中看到的那样,我正在尝试按照一些较旧的 Stack Overflow 帖子( 1、2和3 )的建议实现销毁和重新初始化函数,但我是一个 JS 菜鸟所以我不确定如何进行。
模型.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)
表格.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'))
视图.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 %}