Use AJAX to update Django Model - javascript

I am trying to understand how to update a Django model using AJAX without loading a new page or explicitly having the user press a save button. I have found many tutorials that deal with getting results from Django models using AJAX but I haven't found any that deal with updating models using AJAX.
Here is what I have so far
I have the following Django model:
#models.py
class Upload(models.Model):
email = models.EmailField()
title = models.CharField(max_length=100)
language = models.ForeignKey('about.channel', on_delete=models.CASCADE, default='Other')
date = models.DateField(auto_now_add=True)
file = models.FileField()
completed = models.BooleanField(default=False)
I am accepting those uploads through a form, all is well. I am then displaying those on a page through the following view:
#views.py
def submissions(request):
context = {
'uploads': Upload.objects.all().order_by('-completed', '-date')
}
return render(request, 'content/submissions.html', context)
The template for this page:
#submissions.html
<div class="row row-cols-1 row-cols-md-3">
{% for upload in uploads %}
<div class="col mb-4">
<div class="card">
<div class="card-body">
<h5 class="card-title"> {{ upload.title }} </h5>
<h6 class="card-subtitle"> {{upload.language}} </h6>
<a href="{{ upload.file.url }}" class="channel-link card-link" download> Download </a>
{% if upload.completed %}
<div class="form-check">
<input class="form-check-input" type="checkbox" value="" data-id="{{ upload.id }}" checked>
<label class="form-check-label" for="{{ upload.id }}"> Completed </label>
</div>
{% else %}
<div class="form-check">
<input class="form-check-input" type="checkbox" value="" data-id="{{ upload.id }}">
<label class="form-check-label" for="{{ upload.id }}"> Completed </label>
</div>
{% endif %}
</div>
</div>
</div>
{% endfor %}
</div>
Here is a portion of the page:
The checkboxes work, and returns the appropriate checked vs unchecked on the completed model field.
I am trying to understand how to connect this to AJAX in order to be able to update the completed model field from just clicking the checkbox located on each card on the page without having to load a new page/model or press a save button. I have tried the following view for updating the model but no luck:
#views.py
def completed(request, *args, **kwargs):
upload = Upload.objects.get(id=id)
upload.completed = not upload.complete
upload.save()
return JsonResponse({'status': 200})
And the jQuery/AJAX:
$('.form-check').on('click', '.form-check-input', function() {
var dataID = $(this).data('id');
$.ajax({
type: 'POST',
url: 'content/completed/',
data: {
id: dataID
},
success: function () {
console.log('Success')
}
})
});
Alas, I get nothing. I'm sure I have things wrong in both my view I'm using to update and the AJAX call, but I'm at a loss for what to do next.

I am assuming your form is firing off your AJAX call successfully with the correct data. Maybe you aren't accessing your AJAX post parameter correctly
Your api:
def completed(request)
id = request.POST.get('id') # Add this line
upload = Upload.objects.get(id=id)
upload.completed = not upload.complete
upload.save()
return JsonResponse({'status': 200})
If this doesn't solve it, let me know what messages you are getting from the backend, and what sort of data you sent in your Ajax call. If you use FireFox, press ctrl+shift+I and click on Network tab to see what data you sent from your Ajax call.
In regard to your comment about CSRF, try putting this code (csrfSafeMethod() and $.ajaxSetup()) before you call your $.ajax()
function csrfSafeMethod(method) {
// these HTTP methods do not require CSRF protection
return (/^(GET|HEAD|OPTIONS|TRACE)$/.test(method));
};
...
$('.form-check').on('click', '.form-check-input', function() {
var dataID = $(this).data('id');
$.ajaxSetup({
beforeSend: function (xhr, settings) {
if (!csrfSafeMethod(settings.type) && !this.crossDomain) {
// Only send the token to relative URLs i.e. locally.
xhr.setRequestHeader("X-CSRFToken", Cookies.get('csrftoken'));
}
}
});
$.ajax({
url: "content/completed/",
type: "POST",
data: {
id: dataID
},
success: function () {
console.log('Success')
}
})
});
This was how I handled CSRF for my APIs without putting them into #csrf_exempt, maybe it will work for you too

Related

How to fetch data from the database in Django on clicking submit?

I need to get database objects on the HTML only when the the SUBMIT is clicked and not on page load. I currently have an AJAX script running on the same form where it returns the text entered in textbox onto the HTML when submit is clicked. I want this feature to stay as well as add a new feature of retrieval of data. Below are some of the code snippets I am using:
views.py
#csrf_exempt
def chat(request):
resps = Responses.objects.all()
context = {'resps' : resps}
return render(request, "chat.html", context)
urls.py
path('chat/', views.chat, name='chat'),
chat.html
<form id="testForm" name="test-form" class="test-form" action="" method="POST">{% csrf_token %}
<input id="texting" name="texting" type="text" class="test-text" placeholder="Test here"/>
<div class="footer">
<input type="submit" value="SEND">
</form>
</div>
{% for r in resps %}
<div>
<p>{{r.response}}</p>
</div>
{% endfor %}
................................................
<script type="text/javascript">
$(document).on('submit','#testForm', function(e){
e.preventDefault();
$.ajax({
type : 'POST',
url : '/chat/',
data :{
text : $('#texting').val(),
csrfmiddlewaretoken: $('input[text=csrfmiddlewaretoken]').val()
},
success : function(){
// alert("Done!");
document.getElementById("userSpeaks").innerHTML = document.getElementById('texting').value;
}
});
});
</script>
Any help would be appreciated. I just need a way out to print the model objects on each click of the submit button and not automatically on page load. Thanks in advance.
Please change the line
csrfmiddlewaretoken: $('input[text=csrfmiddlewaretoken]').val()
to
csrfmiddlewaretoken: $('input[name=csrfmiddlewaretoken]').val()
So you will have to send your querylist as a json object if you want it to be sent through ajax
from django.http import JsonResponse
from django.core.serializers import serialize
#csrf_exempt
def chat(request):
data = {
'resps': serialize("json", Responses.objects.all())
}
return JsonResponse(data)
and you success will look something like this
success : function(data){
// alert("Done!");
resps = JSON.parse(data.resps);
var htmldata=""
for(var x in resps){
htmldata+="<p>"+resps[x].fields.xyz+"</p>"
}
$("#userSpeaks").html(htmldata);
}

Why doesn't the 'follow' button on django work?

I'm using Django 2.2 and PostgreSql. I'm trying to create a simple app that I want to follow neighboring users. 'Follow' button will increase the number of followed, 'Unfollow' button will decrease the number of followed. However, the 'Follow' button does not work. How can I solve this problem?
following/models.py
class Following(models.Model):
follower = models.ForeignKey(User, on_delete=models.CASCADE, related_name='fallower', null=True)
followed = models.ForeignKey(User, on_delete=models.CASCADE, null=True, related_name='fallowing')
following/views.py
def user_follow_unfollow(request):
response = sub_user_follow_unfollow(request)
data = response.get('data')
followed = response.get('followed')
numbers_followed_and_follower= Following.user_followed_and_follower(followed)
context = {'user': followed, 'followers': numbers_followed_and_follower['followers'],
'followeds': numbers_followed_and_follower['followeds']}
html = render_to_string('following/following_partion.html', context=context, request=request)
data.update({'html': html})
return JsonResponse(data=data)
def sub_user_follow_unfollow(request):
if not request.is_ajax():
return HttpResponseBadRequest()
data = {'follow status': True, 'html': '', 'is_valid': True, 'msg': '<b>Unfollow</b>'}
follower_username = request.GET.get('follower_username', None)
followed_username = request.GET.get('followed_username', None)
follower = get_object_or_404(User, username=follower_username)
followed = get_object_or_404(User, username=followed_username)
does_follow_the_user= Following.user_does_follow_the_user(follower=follower, followed=followed)
if not does_follow_the_user:
Following.user_follow(follower=follower, followed=followed)
else:
Following.user_unfollow(followed=followed, follower=follower)
data.update({'msg': '<b>Follow</b>', 'follow_status': False})
return {'data': data, 'followed': followed}
templates.following_partion.html
{% if request.neighbor_detail != user %}
<div>
<button followed='{{ neighbor_detail.username }}' followed='{{ request.neighbor_detail.username }}'
url="{% url 'following:user_follow_and_unfollow' %}" id="follow_unfollow_button"
class="btn btn-lg btn-success">
{% if does_follow_the_user%}
<b>Unfollow</b>
{% else %}
<b>Follow</b>
{% endif %}
</button>
</div>
{% endif %}
<div class="followers col-lg-offset-3 col-md-3 col-md-offset-3 col-lg-3 text-center">
<span><b>followers</b></span>
<button url="{% url 'following:fallowed-or-fallowers-list' 'fallowers' %}" follow_type="followers"
username="{{ neighbor_detail.username }}" class="follow_button btn-block btn btn-primary">
{{ followers}}
</button>
<div class="followeds col-lg-3 col-md-3 text-center">
<span><b>Followeds</b></span>
<button url="{% url 'following:followed-or-followers-list' 'followed' %}" follow_type="followed"
username="{{ neighbor_detail.username }}" class="follow_button btn-block btn btn-success">
{{ followeds}}
</button>
my script
<script>
$("#follow_unfollow_button").click(function () {
var $this = $(this);
var $url = $this.attr('url');
var $takip_eden = $this.attr('follower');
var $takip_edilen = $this.attr('followed');
var data = {follower_username: $follower, followed_username: $followed};
$.ajax({
url: $url,
type: 'GET',
dataType: 'json',
data: data,
success: function (data) {
if (data.is_valid) {
$this.html(data.msg);
$("#user_following").html(data.html)
}
}
})
});
</script>
We cannot help you as there's too many missing pieces. However, this should not be too difficult to debug, here are some things you should inspect:
In your browser developer tools, inspect the HTTP request (XHR request). What parameters are being sent?
In your python debugger, inspect the values of request.GET, data, numbers_followed_and_follower. If you don't know these, it's impossible to tell what's wrong.
If it's still not clear what's wrong, in your python IDE, set a breakpoint in your view and step through your code line by line, inspecting the results. I cannot stress how important it is to use an IDE with a proper debugger.
In your browser developer tools, inspect the HTTP response to your AJAX request. What is being returned?
You need to analyse step-by-step your various variables to understand where's the issue.
Suggestions
You should really use POST (not GET) in your AJAX call, since you're modifying the database.
Use a ManyToManyField to register followers. They are just a relationship between two users:
follows = models.ManyToManyField("self", symmetrical=False, related_name="followers")
By specifying symmetrical=False you tell Django to distinguish the two directions of the relationship. In order to create or remove the relationship in your view, and to view relationships, you can just:
user.follows.add(other_user) # user follows other_user
user.follows.remove(other_user) # user unfollows other_user
user.followers.all() # people following
user.followers.count() # number of followers

Populate form field with AJAX query

I would like to populate a django form field each time a dropdown value is selected inside a specific field.
Example :
I have a list of businesses (business A, business B, ...) and a list of countries. Each business is located in a specific country.
Business A --> France
Business B --> Germany
Business C --> England
In my form, when I select a specific business in my dropdown list, I would like to populate immediatly the country field with the associated country. If the business change, the associated country too.
I'm using Django 1.11.18
The context :
In my code, MemberState corresponds to the Country as my example above and RBI corresponds to the business.
My Model :
class MemberState(models.Model):
name = models.CharField(max_length=256, verbose_name=_('Name'))
code = models.CharField(max_length=256, verbose_name=_('Code'))
class RBI(models.Model):
short_name = models.CharField(max_length=256, verbose_name=_('Short name'), unique=True)
member_state = models.ForeignKey(MemberState, verbose_name=_('Member State'))
...
My Form :
class FinalProductSearchForm(forms.Form):
releasing_body = ShortNameModelChoiceField(queryset=RBI.objects.filter(active=True).order_by('short_name'), required=False,
widget=forms.Select(), empty_label=_('Select'), label=_('Releasing Body/Institution'))
member_state = forms.ModelChoiceField(queryset=MemberState.objects.filter(active=True).order_by('name'), required=False,
widget=forms.Select(), empty_label=_('Select'), label=_('Member state'))
...
I would like to select a releasing_body in my form and prefill the member_state field associated. Each time I change the realeasing_body it loads the associated member_state.
I tried some things in Django but I need AJAX request. Unfortunatly, I have never done this kind of things.
My work with AJAX part :
So, this is my first try (which doesn't work) :
I created this function in my views.py file :
def ajax_member_state_request(request):
if request.is_ajax():
release_body = request.GET.get('releasing_body', None)
print(release_body)
member_state_ini = ReleaseBodyInstitution.objects.values_list('member_state', flat=True).get(id=release_body)
print(member_state_ini)
member_state = MemberState.objects.get(id=member_state_ini)
print(member_state)
return JsonResponse({'member_state': member_state})
In my urls.py file, I added :
url(r'^finalproduct/list/$', FinalProductListView.as_view(),
name='finalproduct-list'),
url(r'^finalproduct/list/ajax_member_state_request/$', views.ajax_member_state_request, name='ajax_member_state_request'),
And finally in my HTML file :
<form id="providerForm" data-provider-url="{% url 'ajax_member_state_request' %}" class="navbar-search" method="GET" action="{{ url }}">
{% csrf_token %}
<div class="row">
<div class="col-md-5">
{{ search_form.releasing_body|as_crispy_field }}
</div>
<div class="col-md-5">
{{ search_form.member_state|as_crispy_field }}
</div>
</div>
<input type="submit" class="btn btn-default" value="{% trans 'Search' %}" />
<input type="button" class="btn btn-default" name="clear" value="Reset" onclick="clearForm(this.form);">
</form>
The AJAX part looks like this :
$("#id_releasing_body").change(function () {
var url = $("#providerForm").attr("data-provider-url");
var releasingBodyId = $(this).val();
$.ajax({
url: url,
type: 'GET',
dataType: 'json',
data: {
'releasing_body': releasingBodyId
},
success: function (data) {
$("#id_member_state").val(data.member_state);
}
});
});
I would implement a view that given a business name returns a JsonResponse with the country (following your example).
With that in place in the success section of the ajax request set the value of the country form field.
The view:
def contry_for_bussines(request):
if request.is_ajax():
member_state = ReleaseBodyInstitution.objects.get(id=release_body).member_state
return JsonResponse({'member_state': member_state})
In the ajax
$("#id_releasing_body").change(function () {
var url = $("#providerForm").attr("data-provider-url");
var releasingBodyId = $(this).val();
$.get(url, {'releasing_body': releasingBodyId}, function(data){
$("#id_member_state").text(data.member_state);
});
});
Check this approach if it helps, I followed those steps for my project and successfully populated choicefields with AJAX request. The only problem is the form is not binding when submitted despite a value is selected in all fields (working on that now)
https://simpleisbetterthancomplex.com/tutorial/2018/01/29/how-to-implement-dependent-or-chained-dropdown-list-with-django.html

Handle form submission in bootstrap modal with ajax and class based views

i'm quite new using django and i've been stuck in this problem for several days.
I have a form.Form in a bootstrap modal on my template with only 1 field (email_field) and basically i need to submit that form via ajax, check if that email address is registered in the database, then send an invitation to that email and close the modal. if the email is not registered show the form errors without closing the modal. I've tried with different examples but can find the solution either because the examples don't handle errors or the form is not inside a modal or not using class based views
.
I'm having 2 issues with my code:
Not sure what to return in my view if the form is valid or invalid and how to handle errors in my js code to show them on the modal.(return tha form to render the errors or a JSON response??).
After the first success submission is made the form cannot be used again.(The size of the submit button changes and if you click it return a error : CSRF token missing or incorrect)
Form.py
class CollaboratorForm(forms.Form):
email_address = forms.EmailField(required=True,widget=forms.TextInput(attrs={'class': 'form-control focus-text-box', 'type': 'email',
'placeholder': 'Enter email'}))
def clean_email_address(self):
email = self.cleaned_data['email_address']
if not User.objects.filter(email=email):
raise forms.ValidationError('This user is not registered')
return email
def sendEmail(self, datas):
message = "Hello, " + datas['user_name']+" "+ datas['email_from'] + " invited you to collaborate in an existing project. Follow this link if you are interested " + datas['invitation_link']
msg = EmailMessage('Invitation from ' + datas['user_name'],
message, to=[datas['email_to']])
msg.send()
Template.html (project_detail.html)
<script src="{% static '/experiments/js/invite_collaborator.js' %}"></script>
<div class="bootstrap-modal modal fade in" id="collaboratorModal" style="display: none;">
<div class="modal-body">
<form action="{% url 'experiments:invite-collaborator' project_id=project.id %}" method="post" id=collaborator-form >
{% csrf_token %}
<div class="form-group">
{% if collaborator_form.errors %}
<ol>
{% for error in collaborator_form.errors %}
<li><strong>{{ error|escape }}</strong></li>
{% endfor %}
</ol>
{% endif %}
<label class="control-label">Invite someone by email</label>
<div class="input-group mt10">
{{ collaborator_form }}
<span class="input-group-btn">
<input name="collaborator-commit" onClick="invite({{project.id}});" class="btn btn-primary" data-disable-with="Send Invitation" id="invite-button" type="submit">
</span>
</div>
</div>
</form>
</div>
</div>
Url.py
urlpatterns = [
url(r'^(?P<project_id>[0-9]+)/invite_collaborator$', views.InviteCollaborator.as_view(), name='invite-collaborator'),
]
View.py
class ProjectDetail(DetailView):
model = Project
template_name = 'experiments/project_detail.html'
pk_url_kwarg = 'project_id'
def get_context_data(self, **kwargs):
context = super(ProjectDetail, self).get_context_data()
project = get_object_or_404(Project,pk=self.kwargs["project_id"])
context["project"] = project
context["collaborator_form"] = CollaboratorForm()
return context
class InviteCollaborator(FormView):
form_class = CollaboratorForm
template_name = 'experiments/project_detail.html'
def post(self, request, *args, **kwargs):
collaborator_form = CollaboratorForm(data=request.POST)
project_id = request.POST['project_id']
current_project = Project.objects.get(id=project_id)
datas={}
if collaborator_form.is_valid():
cleaned_data = collaborator_form.cleaned_data
email_address = cleaned_data.get('email_address')
user = User.objects.get(pk=request.user.id)
invitation_link = "http://exp.innovationhackinglab.com/projects/"+ str(current_project.id) + "/join/" + current_project.invitation_key
datas['user_name'] = user.first_name + ' ' + user.last_name
datas['email_from'] = user.email
datas['email_to'] = email_address
datas['invitation_link'] = invitation_link
collaborator_form.sendEmail(datas)
data = simplejson.dumps("Success")
return HttpResponse(data, content_type='application/json')
else:
return super(InviteCollaborator, self).form_invalid(collaborator_form)
invite_collaborator.js
function invite(project_id) {
$('#collaborator-form').submit(function(e) {
e.preventDefault();
$.ajax({
data: $(this).serialize()+'&'+$.param({ 'project_id': project_id }),
type: $(this).attr('method'),
url: $(this).attr('action'),
});
$('#collaboratorModal').modal('toggle');
$('#collaboratorModal').on('hidden.bs.modal', function () {
$(this).find("input,textarea,select").val('').end();
});
});
};
I've read about using success: & error: on the js file but don't know how to use it without the appropriate "return" in the view
You need to have two ajax methods, one to get the form (as raw html) and one to post the form. You will have a corresponding get and post method in your view too.
get function of your view class:
def get(self, request, *args, **kwargs):
form = CollaboratorForm()
return render(request,'template.html',{'form':form})
def post(self, request, *args, **kwargs):
form = CollaboratorForm(request.POST)
if form.is_valid():
//save form
//return whatever you want to show on successful form submission
else:
//return bound form as html with errors
return render(request,'template.html',{'form':form})
js functions
have two seperate ajax function one for get (showing form) one for post(submitting form)
If you want to use templates on server's side, with FormView and ajax, I would suggest splitting templates into two parts - wrapper and form, load only wrapper via TemplateView, then fetch form with ajax. That allows you to send form with ajax and put responses (like form with errors) in wrapper.
Change your HTML template - take modal body's to another file, ex.:
project_detail.html
<script src="{% static '/experiments/js/invite_collaborator.js' %}"></script>
<div class="bootstrap-modal modal fade in" id="collaboratorModal" style="display: none;">
<div class="modal-body" id="collaboratorModalContent">
</div>
</div>
project_detail_content.html
<form action="{% url 'experiments:invite-collaborator' project_id=project.id %}" method="post" id=collaborator-form >
{% csrf_token %}
<div class="form-group">
{% if collaborator_form.errors %}
<ol>
{% for error in collaborator_form.errors %}
<li><strong>{{ error|escape }}</strong></li>
{% endfor %}
</ol>
{% endif %}
<label class="control-label">Invite someone by email</label>
<div class="input-group mt10">
{{ collaborator_form }}
<span class="input-group-btn">
<input name="collaborator-commit" onClick="invite({{project.id}});" class="btn btn-primary" data-disable-with="Send Invitation" id="invite-button" type="submit">
</span>
</div>
</div>
</form>
FormView should handle GET and POST - first one to get the form in project_detail_content.html into modal, second for sending email. Fortunately, FormView can do all that for us! (I don't know from where you get that project variable though)
View.py
class InviteCollaborator(FormView):
form_class = CollaboratorForm
template_name = 'experiments/project_detail_content.html'
def form_valid(self, form):
# This method is called when valid form data has been POSTed.
# It should return an HttpResponse.
project_id = self.request.POST['project_id']
current_project = Project.objects.get(id=project_id)
datas={}
cleaned_data = form.cleaned_data
email_address = cleaned_data.get('email_address')
user = User.objects.get(pk=request.user.id)
invitation_link = "http://exp.innovationhackinglab.com/projects/"+ str(current_project.id) + "/join/" + current_project.invitation_key
datas['user_name'] = user.first_name + ' ' + user.last_name
datas['email_from'] = user.email
datas['email_to'] = email_address
datas['invitation_link'] = invitation_link
form.sendEmail(datas)
data = simplejson.dumps("Success")
return HttpResponse(data, content_type='application/json')
Note few things - we use FormView, so for GET request it will return content of project_detail_content.html with CollaboratorForm, and on POST, same template with form and errors if form is invalid, or JSON with Success message otherwise.
What happened to project_detail.html? We will use TemplateView to create thw wrapper:
Url.py
urlpatterns = [
url(r'^invite_collaborator$', TemplateView.as_view(template_name="project_detail.html")),
url(r'^(?P<project_id>[0-9]+)/invite_collaborator/form$', views.InviteCollaborator.as_view(), name='invite-collaborator'),
]
Finally, JS
invite_collaborator.js
// In JS you need to make sure you fetch form from /project_id/invite_collaborator/form each time you show modal
$(document).ready(function(e) {
$('#collaboratorModalContent').load('invite_collaborator');
});
// Then, on submit we simply send data and handle response with success and error.
// With our current View, invalid form will generate successful response with form and error, so we need to check
function invite(project_id) {
$('#collaborator-form').submit(function(e) {
e.preventDefault();
$.ajax({
type: $(this).attr('method'),
url: $(this).attr('action'),
data: $(this).serialize()+'&'+$.param({ 'project_id': project_id }),
success: function ( response, status, xhr, dataType ) {
if( dataType === 'json' ){
//Make sure response is 'Success' and close modal
$('#collaboratorModal').modal('toggle');
$('#collaboratorModal').on('hidden.bs.modal', function () {
$(this).find("input,textarea,select").val('').end();
});
});
};
}
else {
// It's not JSON, it must be HttpResposne with forms and errors, so it goes into modal's body
$('#collaboratorModalContent').html(response)
}
}
});
I still don't know where and how you get/set you project variable, so maybe TemplateView is bad choice...

AJAX post failing XMLHttpRequest check in Django view

I have a simple html page which renders with a number of nearly identical forms for the user to submit. Upon submit, the view is intended to add a row to the database, recreate the list of forms with slightly updated data, and send it back to the browser ('/route/complete/' maps to add_completed_route_view in urls.py).
This works perfectly the first time. Once the page has been redrawn with the new list of forms, however, the next submit will fail the request.is_ajax() test I have in the view. That causes it to skip to request.REQUEST['next'] and subsequently to home_view.
I've commented it out below, but I've also tried appending c['HTTP_X_REQUESTED_WITH'] = 'XMLHttpRequest' to the view but it hasn't helped.
I'm looking for help in ensuring that the headers continue to have the appropriate XMLHttpRequest param while the user submits through AJAX. Code is below, and help is much appreciated.
script.js
<script>
$(document).ready(function() {
$(".doneForm").submit(function() {
var route_id = $(this).find('input[name=route_id]').val()
var next = $(this).find('input[name=next]').val()
var reqData = {route_id:route_id,next:next}
$.ajax({
type: "post",
url: "/route/complete/",
data: reqData,
success: function(data) {
$("#routeTable").html(data);
}
});
return false;
});
});
</script>
and
template.html
<div id="routeTable">
{% for route in route_list %}
<div id="routeDone">
<form class="doneForm" action="/route/complete/" method="post">
<input type="hidden" name="route_id" value="{{ route.route_id }}" />
<input type="hidden" name="next" value="{{ request.get_full_path }}" />
<input type="submit" value="Done" class="doneButton" />
</form>
</div>
{% endfor %}
</div>
and
views.py
def add_completed_route_view(request):
if request.method == 'POST' and request.user.is_authenticated():
add_completed_route(request)
if request.is_ajax():
wall_slug = get_wall_slug_from_route_id(request.REQUEST['route_id'])
c = get_context_for_wall_page(request, wall_slug)
# c['HTTP_X_REQUESTED_WITH'] = 'XMLHttpRequest'
return render_to_response('m/js_route_table.html', c, context_instance=RequestContext(request))
else:
return HttpResponseRedirect(request.REQUEST['next'])
else:
return HttpResponseRedirect(reverse('home_view'))
The problem is that once the Ajax is completed, it replaces the original form with a new one - and this one no longer has the javascript event handler attached, so the next time the form submits via the normal POST method.
Luckily, jQuery has a couple of methods that handle this for you - live and delegate. So instead of $(".doneForm").submit(function() ..., do this:
$(".doneForm").live("submit", function() {...

Categories