首页 > 解决方案 > Django Formset:是否有机会在 CreateView 的 post() 方法中添加缺少的字段内容?

问题描述

我用 a 创建了CreateView一个modelformset,添加了一些 js 来添加或删除其他表单。这是从银行预订条目创建预订的视图。而且由于'from_account'很明显(预订是从某个银行预订条目启动并从url中的银行预订交出pk),我不想在表单中显示这个(selection-)字段。所以我将该字段作为隐藏字段放在表单集中,目的是在帖子中填写它。所有这些都按预期工作,直到提交。

现在,在 post() 方法中,我在 formset.error 中正确看到了缺少字段“bank_account_ta”和“from_account”的错误。由于我不知道 total_forms 编号(可能已使用 js 更改),因此在实例化 formset 类时无法预填充它。

使用 js 在模板中工作是可能的,但不是正确的方法......

我宁愿使用 formset.clean() 方法,但无论我尝试什么,formset.error 仍然像以前一样导致not formset.is_valid().

我的问题:在 post() 中完成表单集数据 (cleaned_data) 的最简单方法是什么?仍然伤害我的另一点:self.object在表单集中定义是否有必要或有帮助,如果是,如何定义?我把它设置为 None 如果我未定义它,我会收到一个丢失的对象错误。

先感谢您。

视图.py

class TransactionMulitCreateView(LoginRequiredMixin, CreateView):
model = Transaction
template_name = 'accounting/transaction_formset.html'
extra_context = {'title': model._meta.verbose_name, }
success_url = reverse_lazy('finance:ta_groups')
TaFormset = modelformset_factory(Transaction,
                                 formset=TransactionBaseFormset,
                                 exclude=('validity_period_start', 'validity_period_end', 'ta_group'),
                                 extra=1)


def get(self, request, *args, **kwargs):
    self.object = None
    ba = BankTransaction.objects.get(pk=self.kwargs['bank_ta_pk'])
    form = self.TaFormset(queryset=Transaction.objects.none(), initial=[
        {
            # commented out, as it was the js approach.
            # 'bank_account_ta': ba,
            # 'from_account': ba.account.ca_account,
            'posting_text': ba.booking_string(),
            'valuta': ba.valuta,
            'entry_date': ba.entry_date,
            'value': ba.amount,
        },
    ], ba=ba)
    helper = TransactionMultiFormsetHelper()
    return self.render_to_response(self.get_context_data(form=form, helper=helper, bank_ta=ba))

def post(self, request, *args, **kwargs):
    self.object = None
    ba = BankTransaction.objects.get(pk=self.kwargs['bank_ta_pk'])
    # pass in initial to be able to detect changes, see https://docs.djangoproject.com/en/3.1/topics/forms/formsets/
    formset = self.TaFormset(request.POST, request.FILES, initial=[
        {
            # commented out, as it was the js approach.
            # 'bank_account_ta': ba,
            # 'from_account': ba.account.ca_account,
            'posting_text': ba.booking_string(),
            'valuta': ba.valuta,
            'entry_date': ba.entry_date,
            'value': ba.amount,
        },
    ], ba=ba)

    formset.clean()
    # formset = self.TaFormset()
    if formset.is_valid():
        instances = formset.save(commit=False)
        split = TransactionGroup.objects.create(create_by=self.request.user, update_by=self.request.user)
        for instance in instances:
            instance.ta_group = split
            instance.save()
        # BankTransaction.objects.filter(pk=self.kwargs['bank_ta_pk']).update(is_booked=True)
        ba.is_booked = True
        ba.save()
        return HttpResponseRedirect(reverse_lazy('finance:bank_tas'))
        # return self.form_valid(formset)
    else:
        helper = TransactionMultiFormsetHelper()
        return self.render_to_response(self.get_context_data(form=formset, helper=helper, bank_ta=ba))
        # return self.form_invalid(formset)

表格.py

class TransactionBaseFormset(forms.BaseModelFormSet):
def __init__(self, *args, **kwargs):
    # self.ba_pk = kwargs.pop('ba_pk')
    try:
        self.ba = kwargs.pop('ba')
    except KeyError:
        self.ba = None
    super().__init__(*args, **kwargs)

def clean(self):
    data = None
    for form in self.forms:
        data = form.cleaned_data
        data['bank_account_ta'] = self.ba
        data['from_account'] = self.ba.account.ca_account
    return data

标签: pythondjangodjango-views

解决方案


知道了!简单的解决方案是排除所有强制字段并将它们填充到函数中clean()is_valid()函数中。

TaFormset = modelformset_factory(Transaction,
                                 formset=TransactionBaseFormset,
                                 exclude=(
                                     'validity_period_start',
                                     'validity_period_end',
                                     'ta_group',
                                     'bank_account_ta',
                                     'from_account',
                                 ),
                                 extra=1)

但是,我仍然想知道self.object在表单集(或模型集)中扮演(或可能扮演)哪些角色?


推荐阅读