如何防止 Django ModelForm 的验证
How to prevent validation of Django ModelForm
有没有办法阻止对提交的 Django ModelForm 进行验证?
原因是我在该表单中有两个 select 字段,我使用 Ajax 更改了相关的 table。
因此,我需要重新加载表单才能 select new/changed 值,我不想要所有验证错误。
编辑:
我最初的计划是设置隐藏字段 "refresh" 并提交表单 (Ajax)。
在 create_component 中,我想检查刷新的值,return 呈现但未验证的表单并使用 jQuery 替换它。
我希望 form.is_valid() 触发验证过程,但不幸的是,如果我在不调用 is_valid.
的情况下呈现表单,我会得到一个经过验证的表单
views.py
def create_component(request):
if request.method == "POST":
form = ComponentForm(request.POST)
if request.POST.get('refresh',False):
return render(request, "component_form.html", {"form":form})
if form.is_valid():
form.save()
return redirect("material")
else:
form = ComponentForm()
return render(request, "create_component.html", {"form":form})
forms.py
class ComponentForm(ModelForm):
refresh = BooleanField(widget=HiddenInput, required=False)
class Meta:
model = Component
fields = ['name', 'articlenumber', 'manufacturer', 'vendor', 'price', 'picture', 'notes']
labels = {
'name': _('Bezeichnung'),
'manufacturer': _('Hersteller'),
'articlenumber': _('Artikelnummer'),
'vendor': _('Lieferant'),
'price': _('Preis'),
'notes': _('Notizen')
}
widgets = {
'picture': HiddenInput
}
您可以使用 Django 错误消息:https://docs.djangoproject.com/en/1.9/ref/contrib/messages/#adding-a-message
对当前 url 视图执行 AJAX post。然后,您可以使用 AJAX 请求并在表单内的 div 或 p 中显示表单错误。无需刷新。
这是一个使用 AJAX、Django 1.9 和 Python 2.7:
插入注释的示例
forms.py:
#comment form
class InsertComentForm(forms.Form):
comment = forms.CharField(widget=forms.Textarea(attrs={'id': 'comment', 'placeholder': 'Enter a Comment'}),required = True)
views.py:
#inside comment view
InsertComent = forms.InsertComentForm()
if request.is_ajax():
if request.method == 'POST':
InsertComent = forms.InsertComentForm(request.POST)
if request.POST.get("InsertCommentSubmit") is not None: #error
if request.POST.get("comment")=="":
message = "Comment field cannot be empty!"
return HttpResponse(message)
elif User.objects.filter(username = request.user.username).exists():
if InsertComent.is_valid():
article_id = Article.objects.get(title=Slug, pub_date= aTimestamp).pk
article_id = article_id
user_id = request.user.id
p=Comment(comment=InsertComent.cleaned_data['comment'], article_id=article_id, user_id=user_id, date=date.today(), flagged=0, ipAddress=get_ip(request))
p.save()
message="Thanks for commenting!"
return HttpResponse(message)
else:
messages.error(request, "Login to Comment!");
else:
message = "Not Ajax"
return HttpResponse(message)
模板:
<form id="commentForm" class="col-md-12 djangoForm" action="" method="POST">
<p class="formMessage" id="error_msg_comment"> </p><!-- Needs Space for style, AJAX Errors Here-->
<div class="fieldWrapper">
<input type="hidden" name="csrfmiddlewaretoken" id="csrfmiddlewaretoken" value="{{ csrf_token }}">
</div>
<div class="fieldWrapper">
{{ InsertComentForm.comment }}
</div>
<input id="InsertCommentSubmit" name="InsertCommentSubmit" class="Button" type="submit" class="btn btn-default" value="Send" onclick="return InsertCommentForm()"/>
</form>
AJAX:
//Do not forget to pass the csrfmiddlewaretoken!
function InsertCommentForm(){
var comment=document.getElementById('comment').value; //change from name to id!
var csrfmiddlewaretoken=document.getElementById('csrfmiddlewaretoken').value; //change from name to id!
var InsertCommentSubmit=document.getElementById('InsertCommentSubmit').value;//change from name to id!
var dataString = 'comment='+ comment+
'&csrfmiddlewaretoken='+ csrfmiddlewaretoken +
'&InsertCommentSubmit='+ InsertCommentSubmit;
$.ajax({
type: "post",
url : "",
data:dataString,
cache:false,
success: function(html){
if (html==0){
window.location.reload();
//document.getElementById("commentForm").reset();
}else{
$('#error_msg_comment').html(html);
}
}
});
return false;
}
我希望您可以借鉴或使用这个例子!
我终于找到了适合我需要的解决方案。
我使用 Ajax 调用提交表单,从响应中取出更新后的 select 并将原来的 select 替换为:
$("#id_refresh").val(1);
$.post(
$("form").attr("action"),
$("form").serialize(),
function(d) {
$("#id_manufacturer").replaceWith($(d).find("#id_manufacturer"));
$("#id_refresh").val(0);
}
);
这可能是一种 hacky 的方式,但它对我有用。
I get a validated form if I render the form without calling is_valid
...这对我来说听起来不对。
我认为你的实际问题在这里:
if request.POST.get('refresh',False):
...当像这样检查原始 post var(未经您的表单处理)时,该值将始终是一个字符串,因此它将始终与 True
进行比较
(具体来说,如果您在 django/forms/fields.py
中检查 BooleanField
的 src,他们会有一条评论指出 "check for the string 'False', which is what a hidden field will submit for False")
所以您获得经过验证的表单的原因是因为您的代码遵循 form.is_valid
代码路径。
您可能会发现从表单 class 中删除 refresh
字段(我认为这只是您的 hack 所需的),而不是手动附加 ?refresh=1
querystring 更容易从您的 javascript 到 POST url。这在您看来更容易解析:
if int(request.GET.get('refresh', '0')):
有没有办法阻止对提交的 Django ModelForm 进行验证?
原因是我在该表单中有两个 select 字段,我使用 Ajax 更改了相关的 table。 因此,我需要重新加载表单才能 select new/changed 值,我不想要所有验证错误。
编辑:
我最初的计划是设置隐藏字段 "refresh" 并提交表单 (Ajax)。 在 create_component 中,我想检查刷新的值,return 呈现但未验证的表单并使用 jQuery 替换它。 我希望 form.is_valid() 触发验证过程,但不幸的是,如果我在不调用 is_valid.
的情况下呈现表单,我会得到一个经过验证的表单views.py
def create_component(request):
if request.method == "POST":
form = ComponentForm(request.POST)
if request.POST.get('refresh',False):
return render(request, "component_form.html", {"form":form})
if form.is_valid():
form.save()
return redirect("material")
else:
form = ComponentForm()
return render(request, "create_component.html", {"form":form})
forms.py
class ComponentForm(ModelForm):
refresh = BooleanField(widget=HiddenInput, required=False)
class Meta:
model = Component
fields = ['name', 'articlenumber', 'manufacturer', 'vendor', 'price', 'picture', 'notes']
labels = {
'name': _('Bezeichnung'),
'manufacturer': _('Hersteller'),
'articlenumber': _('Artikelnummer'),
'vendor': _('Lieferant'),
'price': _('Preis'),
'notes': _('Notizen')
}
widgets = {
'picture': HiddenInput
}
您可以使用 Django 错误消息:https://docs.djangoproject.com/en/1.9/ref/contrib/messages/#adding-a-message
对当前 url 视图执行 AJAX post。然后,您可以使用 AJAX 请求并在表单内的 div 或 p 中显示表单错误。无需刷新。 这是一个使用 AJAX、Django 1.9 和 Python 2.7:
插入注释的示例forms.py:
#comment form
class InsertComentForm(forms.Form):
comment = forms.CharField(widget=forms.Textarea(attrs={'id': 'comment', 'placeholder': 'Enter a Comment'}),required = True)
views.py:
#inside comment view
InsertComent = forms.InsertComentForm()
if request.is_ajax():
if request.method == 'POST':
InsertComent = forms.InsertComentForm(request.POST)
if request.POST.get("InsertCommentSubmit") is not None: #error
if request.POST.get("comment")=="":
message = "Comment field cannot be empty!"
return HttpResponse(message)
elif User.objects.filter(username = request.user.username).exists():
if InsertComent.is_valid():
article_id = Article.objects.get(title=Slug, pub_date= aTimestamp).pk
article_id = article_id
user_id = request.user.id
p=Comment(comment=InsertComent.cleaned_data['comment'], article_id=article_id, user_id=user_id, date=date.today(), flagged=0, ipAddress=get_ip(request))
p.save()
message="Thanks for commenting!"
return HttpResponse(message)
else:
messages.error(request, "Login to Comment!");
else:
message = "Not Ajax"
return HttpResponse(message)
模板:
<form id="commentForm" class="col-md-12 djangoForm" action="" method="POST">
<p class="formMessage" id="error_msg_comment"> </p><!-- Needs Space for style, AJAX Errors Here-->
<div class="fieldWrapper">
<input type="hidden" name="csrfmiddlewaretoken" id="csrfmiddlewaretoken" value="{{ csrf_token }}">
</div>
<div class="fieldWrapper">
{{ InsertComentForm.comment }}
</div>
<input id="InsertCommentSubmit" name="InsertCommentSubmit" class="Button" type="submit" class="btn btn-default" value="Send" onclick="return InsertCommentForm()"/>
</form>
AJAX:
//Do not forget to pass the csrfmiddlewaretoken!
function InsertCommentForm(){
var comment=document.getElementById('comment').value; //change from name to id!
var csrfmiddlewaretoken=document.getElementById('csrfmiddlewaretoken').value; //change from name to id!
var InsertCommentSubmit=document.getElementById('InsertCommentSubmit').value;//change from name to id!
var dataString = 'comment='+ comment+
'&csrfmiddlewaretoken='+ csrfmiddlewaretoken +
'&InsertCommentSubmit='+ InsertCommentSubmit;
$.ajax({
type: "post",
url : "",
data:dataString,
cache:false,
success: function(html){
if (html==0){
window.location.reload();
//document.getElementById("commentForm").reset();
}else{
$('#error_msg_comment').html(html);
}
}
});
return false;
}
我希望您可以借鉴或使用这个例子!
我终于找到了适合我需要的解决方案。 我使用 Ajax 调用提交表单,从响应中取出更新后的 select 并将原来的 select 替换为:
$("#id_refresh").val(1);
$.post(
$("form").attr("action"),
$("form").serialize(),
function(d) {
$("#id_manufacturer").replaceWith($(d).find("#id_manufacturer"));
$("#id_refresh").val(0);
}
);
这可能是一种 hacky 的方式,但它对我有用。
I get a validated form if I render the form without calling is_valid
...这对我来说听起来不对。
我认为你的实际问题在这里:
if request.POST.get('refresh',False):
...当像这样检查原始 post var(未经您的表单处理)时,该值将始终是一个字符串,因此它将始终与 True
(具体来说,如果您在 django/forms/fields.py
中检查 BooleanField
的 src,他们会有一条评论指出 "check for the string 'False', which is what a hidden field will submit for False")
所以您获得经过验证的表单的原因是因为您的代码遵循 form.is_valid
代码路径。
您可能会发现从表单 class 中删除 refresh
字段(我认为这只是您的 hack 所需的),而不是手动附加 ?refresh=1
querystring 更容易从您的 javascript 到 POST url。这在您看来更容易解析:
if int(request.GET.get('refresh', '0')):