2

我有一个使用Django Dynamic Formset以及Crispy FormsTempus Dominus datepicker 库设置的模型表单集。这是一个简单的表单集,供用户添加运营费用行条目——日期、类别、描述和金额。

我的日期选择器可以与非动态表单集一起正常工作。但是,当使用动态表单集并添加新表单时,小部件最终会定位到从中克隆它的表单集中的最后一个表单,而不是当前表单 ( https://imgur.com/a/2GFYZ90 )。它不是正确递增(即 form_3、form_4、form_5 等),而是指在添加新表单之前的最后一个表单(即 form_2)。因此,如果我尝试在任何动态添加的表单中切换日期选择器,它只会触发 form_2 中的那个。常规文本字段可以正确克隆,没有任何问题。

正如您在 opex.html 的第 19-23 行中看到的那样,我正在尝试按照一些较旧的 Stack Overflow 帖子( 123 )的建议实现销毁和重新初始化函数,但我是一个 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 %}
4

0 回答 0