Django Ajax提交验证和多个表单处理

时间:2014-07-24 11:35:01

标签: jquery python ajax django forms

在Django管理界面中,可以很好地将新项目动态添加到外键字段,我想使用bootstrap模式为弹出窗口和Ajax进行表单提交和验证。

这是我的用例:

这是添加项目的主要表单。物品有参考和类别。

enter image description here

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

enter image description here

显示模态并提交表单以添加新类别我没有问题。 相反,问题在于表单验证(如果用户提交空表单),并刷新选择内容以添加新添加的类别。

这是我的代码:

forms.py

class ItemForm(forms.ModelForm):
    ref = forms.CharField(widget=forms.TextInput(attrs={'class':'form-control'}),max_length=255)
    category =  forms.ModelChoiceField(queryset=ItemCategory.objects.all(), empty_label="(choose from the list)")


class ItemCategoryForm(forms.ModelForm):
    category = forms.CharField(
        max_length=255,
        required=True,
        help_text='Add a new category')

views.py

def add(request):
    if request.method == 'POST':
        form = ItemForm(request.POST)
        if form.is_valid():
            item= Item()
            item.ref = form.cleaned_data.get('ref')
            item.save()
            return redirect('/item_list/')
    else:
        form = ItemForm()
        form1 = ItemCategoryForm()
    return render(request, 'item/add.html', {'form': form, 'form1':form1}) 

def add_category(request):
    if request.method == 'POST':
        form1 = ItemCategoryForm(request.POST)
        if form1.is_valid():
            vulnCategory = ItemCategory()
            ItemCategory.category = form1.cleaned_data.get('category')
            ItemCategory.save()          
     if request.is_ajax():
                #TODO: What Should I redirect
            else:
                #TODO: What Should I redirect
    else:
       #TODO: What Sould I do to return errors without reloding the page and to refresh the list of categories

urls.py

url(r'^add/$', 'add', name='add'),
url(r'^add_category/$', 'add_category', name='add_category'),

我还添加了这个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);
  }
});
});
PS:我知道它可能是重复的,但没有答案让我明白了。

3 个答案:

答案 0 :(得分:6)

在我为内联添加项目的相关类别的解决方案之下。

使用相同的表单,网址作为问题并添加

添加类别

的视图
@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})

Javascript代码

我的解决方案中棘手的部分是将模态和man形式分成两个不同的html文件,并使用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');
                 }
             }
         });
     }); });

答案 1 :(得分:3)

这就是我过去的做法。请注意,这是一个非常简略的版本,并假设它是所有的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)

如果表单无效,您可以使用错误&#39;在ajax帖子上捕获500代码的方法,并重新显示包含所有表单错误的表单。这样你就可以保持表单和模态打开,这样用户就可以纠正错误

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

答案 2 :(得分:1)

ModelChoiceField验证表单中对象的选择,如果为空,则表单不会验证。您可以使用{{form.non_field_errors}}和{{field.errors}}来调试此操作,以指出表单未经过验证的确切原因。

作为一个建议,当我有一个类似的用例时,我使用了Dajax和Dajaxice,他们为我做了很棒的工作。我使用了ChoiceFields,但它们甚至可以用于ModelChoiceFields。

以下是ChoiceFieldForm Submission

的示例