有没有办法通过 ajax 提高正常的 Django 表单验证?

Posted

技术标签:

【中文标题】有没有办法通过 ajax 提高正常的 Django 表单验证?【英文标题】:Is there a way to raise normal Django form validation through ajax? 【发布时间】:2018-07-21 00:08:21 【问题描述】:

我发现了一个有点过时的similar question。我想知道是否可以不使用另一个库。

目前,forms.ValidationError 将触发 form_invalid,它只会返回带有错误和状态代码的 JSON 响应。 我有一个 ajax 表单,想知道在提交 ajax 表单时是否可以在表单字段上进行通常的 django 字段验证。

我的表单触发错误:

class PublicToggleForm(ModelForm):
    class Meta:
        model = Profile
        fields = [
            "public",
        ]
    def clean_public(self):
        public_toggle = self.cleaned_data.get("public")
        if public_toggle is True:
            raise forms.ValidationError("ERROR")  
        return public_toggle  

ajax对应View的mixin:

from django.http import JsonResponse

class AjaxFormMixin(object):

    def form_invalid(self, form):
        response = super(AjaxFormMixin, self).form_invalid(form)
        if self.request.is_ajax():
            return JsonResponse(form.errors, status=400)
        else:
            return response

    def form_valid(self, form):
        response = super(AjaxFormMixin, self).form_valid(form)
        if self.request.is_ajax():
            print(form.cleaned_data)
            print("VALID")
            data = 
                'message': "Successfully submitted form data."
            
            return JsonResponse(data)
        else:
            return response

观点:

class PublicToggleFormView(AjaxFormMixin, FormView):
    form_class = PublicToggleForm
    success_url = '/form-success/'  

在浏览器控制台上,错误将以 400 Bad Request 的形式出现,然后是具有正确 ValidationError 消息的 responseJSON。

编辑:有什么方法可以让字段验证显示客户端?

编辑:附加代码:

前端收到的数据的完整副本:

readyState: 4, getResponseHeader: ƒ, getAllResponseHeaders: ƒ, setRequestHeader: ƒ, overrideMimeType: ƒ, …
abort:
ƒ (a)
always:
ƒ ()
catch:
ƒ (a)
done:
ƒ ()
fail:
ƒ ()
getAllResponseHeaders:
ƒ ()
getResponseHeader:
ƒ (a)
overrideMimeType:
ƒ (a)
pipe:
ƒ ()
progress:
ƒ ()
promise:
ƒ (a)
readyState:
4
responseJSON:
public:
["ERROR"]
__proto__:
Object
responseText:
""public": ["ERROR"]"
setRequestHeader:
ƒ (a,b)
state:
ƒ ()
status:
400
statusCode:
ƒ (a)
statusText:
"Bad Request"
then:
ƒ (b,d,e)
__proto__:
Object  

模板中的表单是使用 Django 的 as_p 渲染的:

% if request.user == object.user %
        Make your profile public?
        <form class="ajax-public-toggle-form" method="POST" action='% url "profile:detail" username=object.user %' data-url='% url "profile:public_toggle" %'>

            public_toggle_form.as_p|safe
        </form>
    % endif %  

javascript

$(document).ready(function()
    var $myForm = $('.ajax-public-toggle-form')
    $myForm.change(function(event)
        var $formData = $(this).serialize()
        var $endpoint = $myForm.attr('data-url') || window.location.href // or set your own url

        $.ajax(
            method: "POST",
            url: $endpoint,
            data: $formData,
            success: handleFormSuccess,
            error: handleFormError,
        )
    )

    function handleFormSuccess(data, textStatus, jqXHR)
        // no need to do anything here
        console.log(data)
        console.log(textStatus)
        console.log(jqXHR)
    

    function handleFormError(jqXHR, textStatus, errorThrown)
        // on error, reset form. raise valifationerror
        console.log(jqXHR)
        console.log("==2" + textStatus)
        console.log("==3" + errorThrown)
        $myForm[0].reset(); // reset form data
        
)

【问题讨论】:

其实是服务端验证。您填写表单并通过 AJAX 请求将数据发送到验证它的服务器上,并向您发送 JSON 响应,其中表单字段名称作为键,错误作为值,您可以通过 html 页面中的 javascript 显示。 对不起——我的意思是我如何让验证错误显示给客户。我看到验证本身发生在服务器端。但错误消息不会出现在客户端 请在此处发布您作为响应收到的数据以及呈现的表单和 javascript ajax 函数。 @Krystofee 完成 【参考方案1】:

您的错误响应采用 JSON 格式,格式为 field_key: err_codes, ...。然后您所要做的就是例如在每个呈现的表单字段下创建&lt;div class="error" style="display: none;"&gt;&lt;/div&gt;,这可以通过手动逐个字段渲染表单字段来完成,或者您可以在表单下方创建一个带有错误的块,例如:

<div id="public_toggle_form-errors" class="form-error" style="display: none;"><div>

在表单中添加一些 CSS:

div.form-error 
    margin: 5px;
    -webkit-box-shadow: 0px 0px 5px 0px rgba(255,125,125,1);
    -moz-box-shadow: 0px 0px 5px 0px rgba(255,125,125,1);
    box-shadow: 0px 0px 5px 0px rgba(255,125,125,1);

所以看起来好像发生了什么错误,然后添加到handleFormError函数代码中:

function handleFormError(jqXHR, textStatus, errorThrown)
    ...
    $('#public_toggle_form-errors').text(textStatus.["public"]);
    $('#public_toggle_form-errors').show();
    ...

我想你会明白的。

【讨论】:

以上是关于有没有办法通过 ajax 提高正常的 Django 表单验证?的主要内容,如果未能解决你的问题,请参考以下文章

使用 django 和 ajax 显示表单错误

Django 评论 - Ajax 和 CSRF 失败

Django 如何让ajax的POST方法带上CSRF令牌

django解决ajax跨域请求

取消表单文件上传提交

在 django 应用程序中加载的 Ajax 调用时间