【问题标题】:Dynamically add form to formset in Django and submit with AJAX在 Django 中将表单动态添加到表单集并使用 AJAX 提交
【发布时间】:2015-10-29 19:31:02
【问题描述】:

我已经阅读了很多关于如何在 Django 中动态地将表单添加到模型表单集中的答案,并且可以成功地实现它。但是,我现在想用 AJAX 提交表单集。这现在大部分都在工作,但我有一个问题在任何其他答案中都找不到解决方案:

如果您动态地将一个表单添加到表单集,则您给它一个新的表单 ID 编号,该编号比该表单当前拥有的最大值大一,并且您还将管理 TOTAL_FORMS 计数增加一。然后新添加的表单成功保存为新对象。

我正在尝试通过 AJAX 提交,以便用户无需刷新页面即可继续编辑。表单集保存得很好,但任何动态添加的表单现在都是现有对象。为了解决这个问题,我需要在保存成功时增加管理表单上的 INITIAL_FORMS 计数。很容易。但是,我也意识到我需要给新创建的对象一个 ID,因为它们现在存在于数据库中。

如何让我的视图在它对 AJAX 调用的响应中告诉我新对象的 ID?或者有没有更好的方法来看待这个?

【问题讨论】:

  • 但是,如果我的想法是错误的,请告诉我,如果您使用 AJAX,则不需要表单集,因为您只提交一个表单.. 现在阅读整个问题。我问你的问题,你的观点是什么?我会做到JSON?
  • 感谢您的回复,但我认为这不能解决我的问题。它只是向表单集添加了一个新表单吗?
  • 是视图返回 JSON。目前它只是返回一小段代码来确认验证是否成功,或者返回一个适用于表单的错误数组。
  • 直截了当,您希望:1) 使用一些 javascript 动态添加和删除项目,以及 2) 使用 AJAX 一次保存所有项目,然后继续编辑项目列表。正确的?所以你的问题是确保新添加的项目不会在用户第二次推送保存时再次添加?

标签: ajax django django-forms


【解决方案1】:

在您看来,保存对象的位置,保存后,object.id 将包含对象的新 id,您可以通过 json 或您想要的 ajax 响应返回,然后是的,您将需要将其填写到表单集行中,以便下次提交。

您必须注意的一件事是 django 期望所有现有行都位于表单集的顶部,而任何新行都位于底部。否则,表单集保存将抱怨缺少 id。因此,如果您在您的 javascript 中进行任何类型的排序,则不能这样做.. 除非您对表单集中的所有字段名称等进行了相当多的修复。 formset 代码使用管理表单中的数字来确定要插入哪些行以及要更新哪些行,它不会根据是否存在 id 来执行此操作。可惜……

【讨论】:

    【解决方案2】:

    Django 表单和表单集旨在用于经典的基于浏览器的数据发布。虽然它们绝对可以与 Javascript 一起使用,但您越想脱离正常行为,它就越复杂。

    根据您的要求,您可能会开始考虑放弃它并切换到 Javascript + REST 端点。当然,如果您需要渐进式增强并且需要在没有 javascript 的情况下使其工作,那不是一个选择。

    在任何情况下,您都希望有一个自定义视图用于从 JS 发布,这样您就可以返回结果并在您的 AJAX 处理程序中轻松解析它。可能是一些 JSON。

    您可以采取多种方法。

    • 让您的 AJAX 将数据发送到不同的 URL。如果您有一个 API 或计划在某个时候构建一个 API,那么这是相关的。因此,您的表单在正常提交时将进行旧式处理,但您的 AJAX 将改为与 API 端点对话。

      例如,您的表单发送到 https://example.com/myform,但您的 Javascript 代码在 https://example.com/api/v1/mymodel/ 与 REST api 通信(根据需要发送 PUT、POST 和 DELETE 请求)。

    • 或者,如果您没有 API 并且构建 API 似乎过大,您可以更改视图,使其输出格式不同,具体取决于数据是以常规方式提交还是使用 AJAX。

      你可以这样处理:

      class MyFormView(.....):
          def render_to_response(self, context, **kwargs):
              if self.request.is_ajax():
                  return self.render_to_json(context, **kwargs)
              return super().render_to_response(context, **kwargs)
      
          def render_to_json(context, **kwargs):
              data = {
                  # see below!
              }
              return HttpResponse(
                  content=json.dumps(data).encode('ascii'),
                  content_type='application/json',
              )
      

      这只是一个大纲。您需要确保is_ajax 能够正确检测到它(请参阅django doc)。并且您需要从context 正确构建data:提取您想要发送回您的JS 代码的内容并将它们放入dict 中。

      如果您只为项目中的一个(可能是两个)视图执行此操作,您会发现它是易于管理的,但很快您就会想要一个小型 API,尤其是考虑到使用以下包构建一个非常容易Django REST framework.

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2020-01-22
      • 2015-02-14
      • 2018-08-26
      • 2017-07-26
      • 2015-02-14
      相关资源
      最近更新 更多