Jquery Django Ajax提交,带有验证和多表单处理

Jquery Django Ajax提交,带有验证和多表单处理,jquery,python,ajax,django,forms,Jquery,Python,Ajax,Django,Forms,在Django管理界面中,可以动态地向外键字段添加新项,我想使用bootstrap模式为弹出窗口创建一个类似的窗口,并使用Ajax进行表单提交和验证 这是我的用例: 这是添加项目的主要表单。项目有一个ref和一个category 这是添加新类别的第二种形式 我在显示模式和提交表单以添加新类别方面没有问题。 相反,问题在于表单验证(如果用户提交一个空表单),以及刷新select内容以添加新添加的类别 这是我的代码: forms.py views.py url.py 我还添加了这个jQuery函

在Django管理界面中,可以动态地向外键字段添加新项,我想使用bootstrap模式为弹出窗口创建一个类似的窗口,并使用Ajax进行表单提交和验证

这是我的用例:

这是添加项目的主要表单。项目有一个ref和一个category

这是添加新类别的第二种形式

我在显示模式和提交表单以添加新类别方面没有问题。 相反,问题在于表单验证(如果用户提交一个空表单),以及刷新select内容以添加新添加的类别

这是我的代码:

forms.py views.py url.py 我还添加了这个jQuery函数来加载结果

$(".add").click(function () {
$.ajax({
  url: '/items/add_category/',
  data: $("form").serialize(),
  cache: false,
  type: 'post',
  beforeSend: function () {
    $("#add_category .modal-body").html("<div style='text-align: center; padding-top: 1em'><img src='/static/img/loading.gif'></div>");
  },
  success: function (data) {
    $("#add_category .modal-body").html(data);
  }
});
});
$(“.add”)。单击(函数(){
$.ajax({
url:“/items/add_category/”,
数据:$(“表单”).serialize(),
cache:false,
键入:“post”,
beforeSend:函数(){
$(“#add_category.modal body”).html(“”);
},
成功:功能(数据){
$(“#add_category.modal body”).html(数据);
}
});
});

PS:我知道它可能是重复的,但没有一个答案让我直截了当。

ModelChoiceField根据对象验证表单中的选择,如果该选择为空,表单将不会验证。您可以通过使用{form.non_field_errors}}和{{field.errors}}指出表单未得到验证的确切原因来进行调试

作为建议,当我有一个类似的用例时,我使用了Dajax和Dajaxice,它们对我来说工作得非常好。我使用了ChoiceFields,但它们甚至可以与ModelChoiceFields一起使用


这里有一个例子,我过去就是这样做的。请注意,这是一个非常精简的版本,并假设所有ajax请求都能让您了解您可以做什么。你应该可以从这里扩展

if form.is_valid():
  do_form_work()
  # Compile a list of lists (or tuples) of the categories
  # e.g. [[x.pk, x.name] for x in categories]
  categories = get_categories()
  json = json.dumps(categories)
  return HttpRepsonse(json, {'content_type' : 'application/json'})
else:
  # 'template' here is a partial template of just the form
  render(self.request, template, context, status=500)
如果表单无效,您可以在ajaxpost上使用'error'方法捕获500代码,并重新显示包含所有表单错误的表单。这样,您就可以保持表单和模式的打开状态,以便用户可以进行更正


如果表单有效,您可以获取返回的json并在选择列表中重新构建您的选项。

下面是我为内联添加项目相关类别所做的解决方案

使用与问题相同的表单、URL并添加

用于添加类别的视图 Javascript代码 我的解决方案的棘手部分是在两个不同的html文件中分离modal和man表单,并使用jQuery处理新项的添加和选择

此Js代码必须包含在两个html文件中:

// This function is for showing the modal 
 $(function () {

     $(".add_category_show_button").click(function () {
         $.ajax({
             type: 'GET',
             url: '/item/add_category/',
             data: $("form").serialize(),
             cache: false,
             success: function (data, status) {
                 $('#add_category_modal_id').html(data);
                 $('#add_category_modal_id').modal()
             }
         });
     }); });

// This second function is for submitting the form inside the modal and handling validation

 $(function () {

     $(".add_category_submit_button").click(function () {
         $.ajax({
             type: 'POST',
             url: '/item/add_category/',
             data: $("form").serialize(),
             cache: false,
             success: function (data, status) {
                 if (data['stat'] == "ok") {
                     $('#add_category_modal_id').modal('hide');
                     $('#add_category_modal_id').children().remove();
                     $('#id_category')
                         .append($("<option></option>")
                             .attr("value", data['new_itemcategory_key'])
                             .text(data['new_itemcategory_value']))
                         .val(data['new_itemcategory_key']);
                 }
                 else {
                     $('#add_category_modal_id').html(data);
                     $('#add_category_modal_id').modal('show');
                 }
             }
         });
     }); });
//此函数用于显示模式
$(函数(){
$(“.add_category_show_button”)。单击(函数(){
$.ajax({
键入:“GET”,
url:“/item/add_category/”,
数据:$(“表单”).serialize(),
cache:false,
成功:功能(数据、状态){
$('#add_category_modal_id').html(数据);
$('#添加_类别_模态_id')。模态()
}
});
}); });
//第二个函数用于在模式内提交表单并处理验证
$(函数(){
$(“.add_category_submit_button”)。单击(函数(){
$.ajax({
键入:“POST”,
url:“/item/add_category/”,
数据:$(“表单”).serialize(),
cache:false,
成功:功能(数据、状态){
如果(数据['stat']=“正常”){
$('#添加_category_modal_id').modal('hide');
$(“#添加_类别_模态_id”).children().remove();
$(“#id#U类别”)
.append($(“”)
.attr(“值”,数据['new\u itemcography\u key'])
.text(数据['new\u itemcography\u value']))
.val(数据['new_itemcategory_key']);
}
否则{
$('#add_category_modal_id').html(数据);
$(“#添加_category_modal_id”).modal('show');
}
}
});
}); });

您始终可以实现django admin使用的类似方法,它实际上会像您一样加载视图(例如添加一个类别),通过标记is_popup来呈现模板,从而删除不需要加载的部分(边栏、标题等)。如果您以同样的方式实现(这并不难),那么您可以通过django的常规流程(表单验证、保存模型等)处理表单提交和所有事务。django管理界面会打开一个单独的弹出窗口,我希望在同一页面中显示弹出窗口,并在不刷新页面的情况下发送数据,以保护键入的数据不丢失。您可以修改它以生成模式而不是弹出窗口(模式实际上是弹出窗口…)。弹出窗口不会刷新页面,也不会重定向您,它只会在您插入新条目时更新相关字段。我找到了解决我问题的Dajax解决方案,但他们说不建议使用它(couplig staff)()感谢您的回答,我找到了一个基于相同想法的解决方案,我将在稍后详细发布。
$(".add").click(function () {
$.ajax({
  url: '/items/add_category/',
  data: $("form").serialize(),
  cache: false,
  type: 'post',
  beforeSend: function () {
    $("#add_category .modal-body").html("<div style='text-align: center; padding-top: 1em'><img src='/static/img/loading.gif'></div>");
  },
  success: function (data) {
    $("#add_category .modal-body").html(data);
  }
});
});
if form.is_valid():
  do_form_work()
  # Compile a list of lists (or tuples) of the categories
  # e.g. [[x.pk, x.name] for x in categories]
  categories = get_categories()
  json = json.dumps(categories)
  return HttpRepsonse(json, {'content_type' : 'application/json'})
else:
  # 'template' here is a partial template of just the form
  render(self.request, template, context, status=500)
@login_required 
def add_category(request):
      data = {}
     if request.method == 'POST' :
         form = ItemCategoryForm(request.POST)
         if form.is_valid():
             itemCategory= ItemCategory()
             itemCategory.name = form.cleaned_data.get('name')
             itemCategory.save()
             data['new_itemcategory_value'] =  itemCategory.name;
             data['new_itemcategory_key'] =  itemCategory.pk;
             data['stat'] = "ok";
             return HttpResponse(json.dumps(data), mimetype="application/json")
         else:
             data['stat'] = "error";
             return render(request, 'item/add_category_modal.html', {'form': form})
     else:
         form = ItemCategoryForm()
         return render(request, 'item/add_category_modal.html', {'form': form})
// This function is for showing the modal 
 $(function () {

     $(".add_category_show_button").click(function () {
         $.ajax({
             type: 'GET',
             url: '/item/add_category/',
             data: $("form").serialize(),
             cache: false,
             success: function (data, status) {
                 $('#add_category_modal_id').html(data);
                 $('#add_category_modal_id').modal()
             }
         });
     }); });

// This second function is for submitting the form inside the modal and handling validation

 $(function () {

     $(".add_category_submit_button").click(function () {
         $.ajax({
             type: 'POST',
             url: '/item/add_category/',
             data: $("form").serialize(),
             cache: false,
             success: function (data, status) {
                 if (data['stat'] == "ok") {
                     $('#add_category_modal_id').modal('hide');
                     $('#add_category_modal_id').children().remove();
                     $('#id_category')
                         .append($("<option></option>")
                             .attr("value", data['new_itemcategory_key'])
                             .text(data['new_itemcategory_value']))
                         .val(data['new_itemcategory_key']);
                 }
                 else {
                     $('#add_category_modal_id').html(data);
                     $('#add_category_modal_id').modal('show');
                 }
             }
         });
     }); });