在 Django 中返回 AJAX 请求的表单错误

Posted

技术标签:

【中文标题】在 Django 中返回 AJAX 请求的表单错误【英文标题】:Returning form errors for AJAX request in Django 【发布时间】:2011-02-07 03:51:29 【问题描述】:

我一直在寻找有关 Django 和 jQuery 的方法。我在 Django 中构建了一个基本表单。单击提交时,我使用 jQuery 向服务器发出 AJAX 请求以发布我的数据。这一点似乎工作正常,我已经设法保存数据。当表单无效时,Django 返回一个 ValidationError。谁能告诉我如何返回这组错误消息作为对我的 AJAX 请求的响应,以便我可以轻松地使用 JS 遍历它并执行任何操作?

我找到了thissn-p。查看 JS 位 (processJson),您会发现他似乎通过从响应 html 中提取错误消息来获取错误消息。这对我来说似乎有点笨拙。这是最好的方法吗?

对于任何含糊之处,我深表歉意。

提前致谢。

【问题讨论】:

【参考方案1】:

这个问题很老,但我认为最短的答案可能是在这样的视图中使用简单的 json。

from django.utils import simplejson

def ajax(request):
    if request.method == 'POST':
        form = someForm(request.POST)
        if form.is_valid():
            form.save()
            return HttpResponse(something)
        else:
            errors = form.errors
            return HttpResponse(simplejson.dumps(errors))
    else:
        return HttpResponse(something)

现在您可以像上面描述的 Calvin 一样访问您的 jquery 中的数据。 Jquery 可以轻松处理数据,您可以这样做:

var errors = jQuery.parseJSON(data)
    alert(errors.username)

【讨论】:

这行得通。谢谢震动。我的印象是您必须执行“form.errors.as_ul()”或等效项的 json 转储......但这更好。干杯。 jQuery.parseJSON(data) 时数据中的第 1 行第 t 列有语法错误。我的数据以Object readyState: 4, getResponseHeader: .aj... 开头【参考方案2】:

哇,我已经一年没看到这个帖子了。好吧,随着 Django 1.3 和神奇的、未记录的基于类的视图的出现,扩展 Django 的视图相关功能变得更加容易。我的项目大量使用了 Django 基于类的通用 CRUS 视图,需要 AJAX 和 JSON 功能。我添加了一个示例,说明如何修改 Django 的更新视图以支持 AJAX 并以 JSON 格式返回 AJAX 响应。看看:

def errors_to_json(errors):
    """
    Convert a Form error list to JSON::
    """
    return dict(
            (k, map(unicode, v))
            for (k,v) in errors.iteritems()
        )

class HybridUpdateView(UpdateView):
    """
    Custom update generic view that speaks JSON
    """
    def form_valid(self, form, *args, **kwargs):
        """
        The Form is valid
        """
        form.save()

        self.message = _("Validation passed. Form Saved.")
        self.data = None
        self.success = True

        payload = 'success': self.success, 'message': self.message, 'data':self.data

        if self.request.is_ajax():
            return HttpResponse(json.dumps(payload),
                content_type='application/json',
            )
        else:
            return super(HybridUpdateView, self).form_valid(
                form, *args, **kwargs
            )

    def form_invalid(self, form, *args, **kwargs):
        """
        The Form is invalid
        """
        #form.save()

        self.message = _("Validation failed.")
        self.data = errors_to_json(form.errors)
        self.success = False

        payload = 'success': self.success, 'message': self.message, 'data':self.data

        if self.request.is_ajax():
            return HttpResponse(json.dumps(payload),
                content_type='application/json',
            )
        else:
            return super(HybridUpdateView, self).form_invalid(
                form, *args, **kwargs
            )

响应 JSON 包含三个字段 — message(这是人类可读的消息)、data(在这种情况下将是表单错误列表)和 success(即 truefalse,分别表示请求是否成功。)。这在 jQuery 客户端很容易处理。示例响应如下所示:

Content-Type: application/json

"message": "Validation failed.", "data": "host": ["This field is required."], "success": false

这只是我如何将表单错误序列化为 JSON 并在基于类的通用视图中实现它的示例,但也可以将其与常规样式视图一起使用。

【讨论】:

【参考方案3】:

当我使用前端验证时,通常响应包含可以通过点符号 (dataReturned.specificData) 访问的块。

基于您返回数据的内容和方式是如何访问数据的关键。您处理返回的数据越模块化,就越容易访问。

// Start ajax request to server
$.ajax(
    url: '/path_to_service',
    type: 'POST',
    data:  key: value ,

    // Do something with the data
    success: function(data) 
        // Data is everything that is returned from the post
        alert(data);
        // data.message could be a piece of the entire return
        alert(data.message);
     error: function(data)  // Handle fatal errors 
);

【讨论】:

嗨 Calvin,什么是错误,什么是成功?我应该返回一些价值吗?在服务器端,我如何以 JSON 格式返回验证错误列表,以便我可以使用错误函数在客户端列出它们?这是让我感到困惑的一点。谢谢。 成功是您发送服务的内容发回数据。成功时,您将在其中操作数据并对其进行处理(通常更新字段或显示消息)。错误是服务返回致命错误(服务已损坏或某些内容已损坏)。通常你会返回 false 并且什么都不做,但如果你的东西需要服务存在,你会告诉用户服务已经关闭。 JSON 方面的事情由您的后端服务处理。不幸的是,我的后端技能还不够,所以我不能告诉你如何编写服务。【参考方案4】:

您可以使用我的 adjax 库为您处理这个问题。将应用安装在路径上的某处,链接adjax.js 文件并将以下内容添加到您的视图中:

import adjax
@adjax.adjax_response
def my_view(request):
    # prepare my_form with posted data as normal
    adjax.form(request, my_form)

加载adjax.js文件后使用javascript启用表单:

 $('form').adjaxify();

然后享受:-)

更多功能在这里:http://adjax.hardysoftware.com.au/how/。我将在下周发布“1.0”版本,让我知道进展如何。谷歌代码项目在这里:http://code.google.com/p/django-adjax/

【讨论】:

【参考方案5】:

我知道这是一个古老且已回答的问题!还是愿意贡献的。我最喜欢的解决方案是对应该错误 json 的方法使用装饰器。

import traceback,sys,simplejson

def unhandled(e):
  """
     Helper function to format an exception and it's stack
  """
  exc_type, exc_value, exc_traceback = sys.exc_info()
  lines = traceback.format_exception(exc_type, exc_value, exc_traceback)
  stack =  ''.join(line for line in lines)
  return HttpResponse(simplejson.dumps("error":-1, "response": e.message ,"stack":stack), content_type='application/json')


def use_json_except(f):
  def new_f(*args):
    try:
      return f(*args)
    except Exception as e:
      return unhandled(e)
    return new_f

然后你定义你的 Django 方法:

 @use_json_except
 def add_annotation(request):
     ....

装饰器将捕获任何未捕获的异常并输出带有错误信息和堆栈的 json。

我个人觉得对于混合 html 和 json 响应的 django 服务器来说,这是一个非常好的解决方案。

【讨论】:

以上是关于在 Django 中返回 AJAX 请求的表单错误的主要内容,如果未能解决你的问题,请参考以下文章

如何清除以前的 AJAX 响应数据(不是 html/表单数据)? - Django/AJAX

Django 1.9 AJAX 表单 CSRF 令牌 403 错误 - “未设置 CSRF cookie”

在 AJAX 请求后填充 Django 表单

Django Ajax“禁止”错误

Django:如何在 ajax 中返回模型表单集并在模板中使用

使用 django ajax jquery 提交一个文件不起作用的表单