使用 form_class 的 UpdateView 从 POST 中删除命名的提交输入

UpdateView with form_class removes named submit input from POST

我想知道用户点击了哪个提交输入。提交的表单转到使用 ModelFormUpdateView。我已经将 name 属性添加到提交输入中,但是当我在 get_context_data() 中执行 if 'approve' in self.request.POST: 时,它是错误的。我覆盖了 def post() 并且 approvePOST 字典中的一个键。有没有办法让 approvedecline 显示在 get_context_data() 中?

我猜这一定与所涉及的 ModelForm 有关,但是有没有办法在不覆盖 post 方法的情况下通过它,或者我应该把它排除在外吗?

仅供参考,我省略了一些与问题无关的臃肿代码。如果其中有些内容没有意义,我们深表歉意。

models.py

class Definition(DefinitionInfo):
    SEV3 = 'info'
    SEV2 = 'warning'
    SEV1 = 'danger'
    sup_sevs = (
        ('', 'Please select'),
        (SEV3, 'Sev3'),
        (SEV2, 'Sev2'),
        (SEV1, 'Sev1'),
    )
    title = models.CharField(max_length=255)
    description = models.TextField(null=True, blank=True)
    resolution = models.TextField(null=True, blank=True)
    sup_sev = models.CharField(max_length=7, choices=sup_sevs, null=False, blank=False)

forms.py

class DefinitionForm(forms.ModelForm):
    class Meta:
        model = Definition
        fields = ['title', 'sup_sev', 'description', 'resolution']
        widgets = {
            'description': forms.HiddenInput(),
            'resolution': forms.HiddenInput(),
        }

views.py

class DefinitionUpdate(LoginRequiredMixin, UpdateView):
    model = Definition
    context_object_name = 'definition'
    form_class = DefinitionForm
    template_name_suffix = '_form'
    success_url = reverse_lazy('definitions:index')

    def get_context_data(self, **kwargs):
        context = super().get_context_data(**kwargs)
        if self.request.method == 'POST':
            print(f'Post data: {self.request.POST}')
        return context

update_form.html

<form id="defForm" class="container-sm w-50" enctype="multipart/form-data" method="post" action=".">
  {% csrf_token %} {{ form.delete }}
  <div class="row g-3">
    <div class="col-md-10">
      <div class="form-floating mb-3">
        <input type="text" class="form-control form-control-sm bg-dark text-light" id="{{ form.title.auto_id }}" name="{{ form.title.html_name }}" placeholder="Enter title here..." value="{{ form.title.value|default_if_none:'' }}">
        <label class="form-label" for="{{ form.title.id_for_label }}">Title</label>
      </div>
    </div>
    <div class="col-sm">
      <div class="form-floating mb-3">
        {{ form.sup_sev }}
        <label class="form-label" for="{{ form.sup_sev.id_for_label }}">Severity</label>
      </div>
    </div>
  </div>
  <div class="form-floating mb-3">
    {{ form.description }}
    <div id="description" class="form-control form-control-sm bg-dark text-light d-inline-block" style="white-space: pre-wrap;" contentEditable>{{ form.description.value|default_if_none:'' }}</div>
    <label class="form-label" for="{{ form.description.id_for_label }}">Description</label>
  </div>
  <div class="form-floating mb-3">
    {{ form.resolution }}
    <div id="resolution" class="form-control form-control-sm bg-dark text-light d-inline-block" style="white-space: pre-wrap;" contentEditable>{{ form.resolution.value|default_if_none:'' }}</div>
    <label class="form-label" for="resolution">Resolution</label>
  </div>
  <div class="d-grid gap-2 d-md-flex justify-content-md-end">
    <input id="decline" class="btn btn-outline-danger" name="decline" type="submit" value="Decline">
    <input id="approve" class="btn btn-outline-success" name="approve" type="submit" value="Approve">
  </div>
</form>

所以在远离它之后我已经解决了它。

首先,我发现我有一个 Jquery 脚本,它使用 $(this).submit(); 提交表单。当然,这意味着它不是提交输入。因此,通过简单地删除它和 preventDefault(); 它就起作用了。下面是罪魁祸首。它将文本复制到相对隐藏的输入。 (所以我有一个自动调整大小的文本区域,但仍然将信息发送到服务器)

$(document).ready(function() {
    let form = $('#defForm')
    let descDiv = $("#description");
    let resoDiv = $('#resolution');
    form.one('submit', function(e) {
        // e.preventDefault();
        let descTa = $("#id_description");
        let resoTa = $("#id_resolution");
        descTa.val(descDiv.text());
        resoTa.val(resoDiv.text());
        //$(this).submit();
    });
});

第二个原因是我需要在表单中进行一些额外的配置。

我在 ModelForm 中添加了 2 个字段,分别是 approvedecline。每个都是一个不需要的 CharField,包括一个 TextInput 小部件,其属性具有 {'type': 'submit', 'value': 'Approve'}(不是完全需要,但如果您只使用 {{ form.approve }} 在模板)。

这样做不仅可以在get_context_data()中显示self.request.POST中的点击提交,而且还可以显示更有用的form_valid().

class DefinitionForm(forms.ModelForm):
    approve = forms.CharField(widget=forms.TextInput(attrs={'type': 'submit', 'value': 'Approve'}), required=False)
    decline = forms.CharField(widget=forms.TextInput(attrs={'type': 'submit', 'value': 'Decline'}), required=False)
    
    class Meta:
        model = Definition
        fields = ['title', 'sup_sev', 'description', 'resolution']
        widgets = {
            'description': forms.HiddenInput(),
            'resolution': forms.HiddenInput(),
        }