使用 form_class 的 UpdateView 从 POST 中删除命名的提交输入
UpdateView with form_class removes named submit input from POST
我想知道用户点击了哪个提交输入。提交的表单转到使用 ModelForm
的 UpdateView
。我已经将 name 属性添加到提交输入中,但是当我在 get_context_data()
中执行 if 'approve' in self.request.POST:
时,它是错误的。我覆盖了 def post()
并且 approve
是 POST
字典中的一个键。有没有办法让 approve
或 decline
显示在 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 个字段,分别是 approve
和 decline
。每个都是一个不需要的 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(),
}
我想知道用户点击了哪个提交输入。提交的表单转到使用 ModelForm
的 UpdateView
。我已经将 name 属性添加到提交输入中,但是当我在 get_context_data()
中执行 if 'approve' in self.request.POST:
时,它是错误的。我覆盖了 def post()
并且 approve
是 POST
字典中的一个键。有没有办法让 approve
或 decline
显示在 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 个字段,分别是 approve
和 decline
。每个都是一个不需要的 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(),
}