Django Ajax view with validation and processing of multiple forms

There is a good opportunity in the Django admin interface to dynamically add new elements to foreign key fields, and I want to do the same using the upload method for the popup and Ajax to submit and validate the form.

This is my use case:

This is the main form for adding an Item. The item has a link and a category.

enter image description here

And this is the second form to add a new category.

enter image description here

I have no problem showing the modality and submitting the form to add a new category. Instead, the problem is to validate the form (in case the user submits an empty form), and updating the selected content to add a new added category.

This is my code:

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'), 

And I also added this jQuery function to load the result

 $(".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: I know that this can be duplicated, but not the answers give me meaning.

+7
jquery python ajax django forms
source share
3 answers

Below is the decision I made for inline adding a related category for an item.

Using the same forms, urls as question and add

View to add a category

 @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 Code

The hard part of my solution was to separate the modal and masculine forms in two different html files and handle adding and selecting a new element using jQuery.

This Js code should be included in two html files:

 // 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'); } } }); }); }); 
+5
source share

Here's how I did it in the past. Please note that this is a very abridged version and assumes that all ajax requests give you an idea of ​​what you can do. Here you can expand fron.

 if form.is_valid(): do_form_work() # Compile a list of lists (or tuples) of the categories # eg [[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) 

If the form is not valid, you can use the "error" method in the ajax message to catch the 500 code and redisplay the form with all form errors. This way you can keep the form modally open so that the user can correct things.

If the form is valid, you can take the returned json and rebuild your options in the select list.

+3
source share

ModelChoiceField checks the selection in the form against the object and, if empty, the form will not be checked. You can debug this using {{form.non_field_errors}} and {{field.errors}} to indicate exactly why the form is not being validated.

As an assumption, when I had a similar use case, I used Dayax and Dayaxis, and they worked fine for me. Instead, I used ChoiceFields, but they even work with ModelChoiceFields.

Here is an example with ChoiceField and Form Submission

+1
source share

All Articles