【问题标题】:Django key error "request" when using inlineformset使用 inlineformset 时 Django 键错误“请求”
【发布时间】:2020-12-22 15:15:57
【问题描述】:

我在 inlineformset 中创建了一个基于类的 (CreateView)。我需要将request.user 传递给表单以在其中一个表单字段上启用过滤器功能。但是,我在线上收到了Key Error: requestself.request = kwargs.pop('request') 在表单的def __init__(self, *args, **kwargs): 中。我们将不胜感激。
也欢迎我的编程技巧。

models.py:

class ttransactions(models.Model):
    transaction_type = models.CharField(max_length=10, choices=tx_choices)
    description = models.CharField(max_length=50, null=False, blank=False, default='Description')
    transaction_date = models.DateField(default=datetime.today, db_index=True)
    company = models.ForeignKey(tcompany, on_delete=models.PROTECT, db_index=True)


    def __str__(self):
        return self.description


class ttransaction_lines(models.Model):
    transaction = models.ForeignKey(ttransactions, on_delete=models.CASCADE, db_index=True)
    sequence = models.IntegerField()
    transaction_type = models.CharField(max_length=6, choices=debit_credit)
    ledger_account = models.ForeignKey(tledger_account, on_delete=models.PROTECT, db_index=True)
    amount = models.DecimalField(max_digits=14, decimal_places=2, default=0.0)
    quantity = models.IntegerField(blank=True, null=True)
    posted = models.BooleanField(default=True)

forms.py:

class TransactionLinesForm(forms.ModelForm):
    class Meta:
        model = ttransaction_lines
        fields = ['transaction_type', 'ledger_account', 'amount']

    def __init__(self, *args, **kwargs):
        self.request = kwargs.pop('request')
        super(TransactionLinesForm, self).__init__(*args, **kwargs)
        user = self.request.user
        current_company = user.current_company
        self.fields['ledger_account'].queryset = tledger_account.objects.filter(
            company=current_company)

TransactionLineFormset = inlineformset_factory(ttransactions,
                                               ttransaction_lines,
                                               # fields=['transaction_type', 'ledger_account', 'amount'] ,
                                               form=TransactionLinesForm,
                                               can_order=True, can_delete=True)

views.py:

class JournalCreateView(LoginRequiredMixin, CreateView):
template_name = 'accounting/journal.html'
model = ttransactions
transaction_lines_form = TransactionLineFormset
form_class = TransactionsForm
success_url = '/accounting/transaction_list'

def get_form_kwargs(self):
    kwargs = super(JournalCreateView, self).get_form_kwargs()
    kwargs['request'] = self.request
    return kwargs

def get(self, request, *args, **kwargs):
    self.object = None
    form_class = self.get_form_class()
    form = self.get_form(form_class)
    transaction_lines_form = TransactionLineFormset()
    return self.render_to_response(
        self.get_context_data(form=form, transaction_lines_form=transaction_lines_form))

def post(self, request, *args, **kwargs):
    extra_forms = 1
    if 'additems' in request.POST and request.POST['additems'] == 'true':
        formset_dictionary_copy = self.request.POST.copy()
        formset_dictionary_copy['form-TOTAL_FORMS'] = \
            int(formset_dictionary_copy['form-TOTAL_FORMS']) + extra_forms
        transaction_lines_form = TransactionLinesFormSet(formset_dictionary_copy)
        return self.render_to_response(
            self.get_context_data(form=form,
                                  transaction_lines_form=transaction_lines_form))

    self.object = None
    form_class = self.get_form_class()
    form = self.get_form(form_class)

    transaction_lines_form = TransactionLineFormset(self.request.POST)
    if (form.is_valid() and transaction_lines_form.is_valid()):
        return self.form_valid(form, transaction_lines_form)
    else:
        return self.form_invalid(form, transaction_lines_form)

def form_valid(self, form, transaction_lines_form):
    form.instance.company = self.request.user.current_company
    self.object = form.save()

    sequence = 1
    for line in transaction_lines_form:
        line.instance.sequence = sequence
        sequence += 1

    transaction_lines_form.instance = self.object
    transaction_lines_form.save()
    return super().form_valid(form)

def form_invalid(self, form, transaction_lines_form):
    return self.render_to_response(
        self.get_context_data(form=form,
                              transaction_lines_form=transaction_lines_form))

【问题讨论】:

    标签: django django-class-based-views inline-formset


    【解决方案1】:

    您的表单可能会在多个位置进行初始化。不查看 Traceback 就很难找到错误发生的位置。

    因此,最好将过滤逻辑保留在视图中,而不是将“请求”传递给表单。删除表单中的__init__ 方法并在视图中尝试以下代码

    def get(self, request, *args, **kwargs):
        self.object = None
        form_class = self.get_form_class()
        form = self.get_form(form_class)
        transaction_lines_form = TransactionLineFormset()
        transaction_lines_form.form.base_fields['ledger_account'].queryset = \
            tledger_account.objects.filter(company=request.user.current_company)
    
        return self.render_to_response(
            self.get_context_data(form=form, transaction_lines_form=transaction_lines_form))
    

    【讨论】:

    • 感谢您的回复。不幸的是,通过尝试不同的选项,我发送了不正确的 views.py 版本。我在这个问题上更正了它。问题是分类帐帐户在交易行表格上。当我按照您在交易行上的建议更改代码时,我收到错误:ttransaction_linesFormFormSet' 对象没有属性'fields'。你能再帮忙吗。很抱歉数据不正确。
    • 我已经编辑了过滤transaction_lines_form 查询集的答案。请尝试。
    • 再次感谢您的回复。我现在收到一个错误:类型对象 'ttransaction_linesForm' 没有属性 'basefields'。我应该创建一个 BaseModelFormSet 吗?如果是这样,您能否就此提供建议。
    • 对不起。它应该是base_fields。在答案中编辑。
    猜你喜欢
    • 2016-10-23
    • 1970-01-01
    • 1970-01-01
    • 2018-10-11
    • 2019-11-22
    • 2014-10-11
    • 1970-01-01
    • 1970-01-01
    • 2021-01-19
    相关资源
    最近更新 更多