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

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

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

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

提前致谢。

【问题讨论】:

    标签: jquery ajax django django-forms


    【解决方案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 服务器来说,这是一个非常好的解决方案。

        【讨论】:

          猜你喜欢
          • 2016-08-17
          • 1970-01-01
          • 2015-01-12
          • 1970-01-01
          • 1970-01-01
          • 2015-06-02
          • 1970-01-01
          • 1970-01-01
          • 1970-01-01
          相关资源
          最近更新 更多