POST doesn't happen in ajax - python

I have a simple form to submit and test ajax,but it doesn't work and I see any problem in it,I searched alot and there was no more poin-at least I dedn't see ;)
in urls.py
(r'^doctors/shahsavand/visiting/$','DrHub.views.visiting'),
(r'^doctors/shahsavand/visiting/add/$','DrHub.views.ajxTest')
the first URL is to direct to main page and there's this form in main page:
<form method='POST' action=".">
{% csrf_token %}
<ul>
<li>
<label for="start">Start Time: </label><input name="id_startTime" id="id_startTime" type="text" />
</li>
<li>
<label for="end">End Time: </label><input name="id_endTime" id="id_endTime" type="text" />
</li>
</ul>
<input type="submit" id="save_button" name="save_button" value="add" />
</form>
and ajax code in this page:
<script type='text/javascript' src='/static/DrHub/doctors/shahsavand/js/jquery-1.4.1.js'></script>
<script type="text/javascript">
$.ajax({
type:"POST",
url:"{% url DrHub.views.ajxTest %}",
data: {
'start': $('#id_startTime').val(),
'end': $('#id_endTime').val(),
'csrfmiddlewaretoken':$( "#csrfmiddlewaretoken" ).val()
},
success: function(data){
alert(data);
}
});
</script>
in views.py :
def ajxTest(request):
if request.is_ajax():
if request.method == 'POST':
return HttpResponse(simplejson.dumps({'message' : 'awesome'}), mimetype='application/javascript')
else:
return render_to_response('DrHub/doctors/nutrition/test.html', context_instance=RequestContext(request))
I did this to test if ajxTest view is called:
def ajxTest(request):
if request.is_ajax():
raise Http404
else:
pass
and this :
def ajxTest(request):
if request.is_ajax():
raise pass
else:
Http404
but no result and that sounds like my ajax POST is not associated with ajxTest view !!!
edit
when I check firebug I get 403 forbidden error that is for CSRF and I've tryed many things to solve it again no result :(

Add the javascript described in the documentation for csrf and it should fix your problem.

Related

Sending data from Python to HTML in Django

I have a Django project with a form in an HTML file, and I'd like to update the text on the submit button of that form WITHOUT a page reload. Essentially:
I click submit on the form
Python handles the submit with the form data
The button text is updated to say "show result"
If I understand correctly, I have to use AJAX for this. The problem is that the form submit relies on an API call in Python, so the HTML essentially has to always be "listening" for new data broadcasted by the views.py file.
Here's the code I have (which doesn't work, since when I hit submit I'm greeted by a page with the JSON response data and nothing else):
views.py:
def home(request):
if request.method == "POST":
print("Got form type", request.content_type)
return JsonResponse({"text": "show result"})
return render(request, 'home.html')
home.html:
<div class="content" onload="document.genform.reset()">
<form name="genform" autocomplete="off" class="form" method="POST" action="" enctype="multipart/form-data">
{% csrf_token %}
<div class="title-sect">
<h1>AJAX Test Form</h1>
</div>
<div class="submit">
<button id="submit" type="submit">Submit</button>
</div>
</form>
</div>
<script type="text/javascript">
function queryData() {
$.ajax({
url: "/",
type: "POST",
data: {
name: "text",
'csrfmiddlewaretoken': '{{ csrf_token }}',
},
success: function(data) {
var text = data['text'];
var button = document.getElementById('submit');
button.innerHTML = text;
setTimeout(function(){queryData();}, 1000);
}
});
}
$document.ready(function() {
queryData();
});
</script>
I've imported jQuery with the script <script src="https://ajax.aspnetcdn.com/ajax/jquery/jquery-1.9.0.min.js"></script>. Any idea why this doesn't work in its current state? Thanks!

redirect() / render_template() enters the route once again when called from the same route in Flask

I have created a wishlist page which lists the items wishlisted by a user. The user can remove any item from the wishlist by clicking on the Remove button. On clicking the remove button, the HTML <form> submits it to the back-end application. The back-end application then removes the item from the wishlist database and redirects back to the same page using return redirect(url_for('wishlist')).
The problem I am facing is that if the user goes back after removing the item from the wishlist he has to go back twice to reach the page from where the user came from. This is caused due to the redirect that I am performing after removing the item which is necessary to show the updated wishlist.
I have also tried render_template() instead of redirect() but it is also causing the same problem.
Code for back-end:
#app.route('/wishlist/',methods=['GET','POST'])
#login_required
def wishlist():
userid=current_user.get_id()
if request.method=='POST':
toRemove=request.form['remove']
deleteWish=session.query(Wishlist).filter_by(userId=userid,productId=toRemove).one()
session.delete(deleteWish)
session.commit()
return redirect(url_for('wishlist'))
subquery=session.query(Wishlist.productId).filter(Wishlist.userId==userid).subquery()
wishes=session.query(Products).filter(Products.id.in_(subquery))
return render_template("wishlist.html",wishes=wishes)
HTML:
<html>
<body>
{% for wish in wishes %}
<img src={{wish.image_path}} width="150" height="200">
</br>
{{wish.material}}
{{wish.productType}}
</br>
{{wish.price}}
</br>
<form action="{{url_for('wishlist')}}" method="POST" target="_self">
<button name="remove" type="submit" value="{{wish.id}}">Remove</button>
</form>
</br>
{% endfor %}
</body>
</html>
Please suggest me a way to prevent this.
You may want to create a different end point for deleting wishes. This endpoint then redirects to your wish list once deletion is done.
FLASK
#app.route('/wishlist/',methods=['GET','POST'])
#login_required
userid=current_user.get_id()
def wishlist():
subquery=session.query(Wishlist.productId).filter(Wishlist.userId==userid).subquery()
wishes=session.query(Products).filter(Products.id.in_(subquery))
return render_template("wishlist.html")
#app.route('/deletewish', methods = ['GET', 'POST']
def deletewish():
if request.method=='POST':
toRemove=request.form['wish_delete_id']
deleteWish=...
session.delete(deleteWish)
session.commit()
return redirect(url_for('wishlist'))
HTML
<html>
<body>
{% for wish in wishes %}
<img src={{wish.image_path}} width="150" height="200">
</br>
{{wish.material}}
{{wish.productType}}
</br>
{{wish.price}}
</br>
<form method="POST" target="_self">
<button class="remove_wish" type="submit" value={{wish.id}}>Remove</button>
</form>
</br>
{% endfor %}`
<script src='path_to_jquery.js'></script>
<script src='path_to_deletewish.js'></script>
</body>
</html>
JS //deletewish.js content
<script>
$(document).ready(function() {
$('.remove_wish').click(function (event) {
event.preventDefault();
$.ajax({
data : {
wish_delete_id : $(this).val();
},
type : 'POST',
url : '/deletewish',
success: function (data) {
location.reload();
},
error: function (e) {
alert('something went wrong')
}
});
});
})
</script>

Not Found url in django class based view with ajax

I have a problem with "like" functionality. I want to make it possible to like the post, without overloading the whole page. So I used CBV django connected to ajax.
My problem is that it receives: Not Found: /like/ by pressing the "Like" button.
My view:
class PostLikeView(generic.View):
def post(self, request):
post = get_object_or_404(Post, id=request.POST.get('id'))
is_liked = False
if post.likes.filter(id=request.user.id).exists():
post.likes.remove(request.user)
is_liked = False
else:
post.likes.add(request.user)
is_liked = True
context = {
'post': post,
'is_liked': is_liked,
'total_likes': post.total_likes(),
}
if request.is_ajax():
html = render_to_string('post/like_section.html', context, request=request)
return JsonResponse({'form': html})
Below is jquery code:
<script type="text/javascript">
$(document).ready(function(event){
$(document).on('click', '#like', function(event){
event.preventDefault;
var pk = $(this).attr('value');
$.ajax({
type: 'POST',
url: "{% url 'post:post_like' %}",
data: {'id': pk, 'csrfmiddlewaretoken': '{{ csrf_token }}'},
dataType: 'json',
success: function(response){
$('#like-section').html(response['form'])
console.log($('#like-section').html(response['form']))
},
error: function(rs, e){
console.log(rs.responseText);
},
});
});
});
</script>
url to view:
url(r'^like/$', login_required(PostLikeView.as_view()), name='post_like'),
code in html:
<form action="{% url 'post:post_like' %}" method="post">
{% csrf_token %}
{% if is_liked %}
<button type="submit" id="like" name="post_id" value="{{ post.id }}" class="btn btn-danger">Dislike</button>
{% else %}
<button type="submit" id="like" name="post_id" value="{{ post.id }}" class="btn btn-primary">Like</button>
{% endif %}
</form>
I would like the button to work on the principle of not reloading the whole page.
The issue I think is that you've not actually called event.preventDefault in your click event handler (you're missing the brackets). That means that the submit button submits the form, but the form doesn't contain a parameter named id and so get_object_or_404(Post, id=request.POST.get('id')) raises a 404.
Add the missing brackets to event.preventDefault, and also note that the value of id= attributes on HTML elements should be unique within the page. Change the values of the id= attributes on the <button> elements so that they are unique.

Django : SQLite Database is Locked when I build like feature on my home page

I am implementing Like functionality in Web application. Idea is Simple to List number of Post(Blogs) on Home page and Add a Like Button to each post(Blog). It works fine when I build it with normal
<form action='{% url target %}' method='POST'>
But when I implemented this with AJAX call It only allows me to like or dislike a particular post(blog) a single time.i.e One I liked a Post for first time it works, also when I dislike the same Post It works fine, But when I again Like that Post it throws an django.db.utils.OperationalError: database is locked
Also, when I like same post multiple(4 to 5) times it respond in a weird way. I goes in Loop of liking and dislikig post.
like_section.html
<form id="like-form{{ post.id }}">
{% csrf_token %}
<button type="submit" id="{{ post.id }}btn" name="like" value="{{ post.id }}" class="btn upvote">Like</button>
<script type="text/javascript">
{% for like in post.likes.all %}
{% if like != user %}
dislikingPost("{{ post.id }}btn");
{% else %}
likingPost("{{ post.id }}btn");
{% endif %}
{% endfor %}
$(document).ready(function(event){
$(document).on('click', '#{{ post.id }}btn', function(event){
event.preventDefault();
pk = $(this).attr('value');
$.ajax({
type: 'POST',
url: '{% url "like_post" %}',
data: {
'id': pk,
'csrfmiddlewaretoken': '{{ csrf_token }}'
},
success:function(response){
$('#like-form{{ post.id }}').html(response['form'])
// $('#{{ post.id }}btn').style.color = 'green';
}, error: function(er, e){
console.log(er.responseText);
}
});
});
});
</script>
</form>
views.py:
def like_post(request):
all_posts = Posts.objects.all()
print("Insisde Like Post")
print('ID coming from form is', request.POST.get('id'))
post = get_object_or_404(Posts, id=request.POST.get('id')) # for AJAX call
context = {
'all_posts': all_posts,
'post': post
}
if post.likes.filter(id=request.user.id).exists():
post.likes.remove(request.user) # Liking The Post
print("DisLiking the post")
else:
post.likes.add(request.user)
print("Liking the post")
if request.is_ajax():
print('Hey its an AJAX calls') # TEsting AJAX request
html = render_to_string('like_section.html', context, request=request)
return JsonResponse({'form': html})
Note:
1. I am beginner in AJAX.
2. I know SQLite can not handle redundant calls, But why it was working before without AJAX calls.
3. I am not providing models.py and complete template of home page and I don't think they are required.
The Problem was not with the Django code. It was ajax call which was triggering Database more then one time on a single Button Click.
Adding event.stopImmediatePropagation(); below event.preventDefault(); in ajax call works perfect

HTML/Django/Jinja/Python : How to post a fixed value back

This is a HTML template that displays all of the proposals in a database (passed through views.py as a list in the dictionary parameter). I then use a jinja for-loop to go through all the proposals in the database and display their attributes.
How can I Post-request the {{ proposal.id }} back to my python code when the "Learn more" button is clicked? I need this to allow me to display the corresponding values in my other html template.
Sorry if this is a basic question, i'm a high school student and extremely new to django! Thanks alot in advance!
{% block body %}
{% for proposal in proposals %}
<div class="jumbotron">
<h2> Proposal : {{ proposal.title }} </h2>
<h4> Status : {{ proposal.status }} </h4>
<h4> Out of --- Votes: </h4>
<div class="progress">
<div class="progress-bar progress-bar-success" style="width: {{ proposal.votes_for }}%">
<span class="sr-only">35% Complete (success)</span>
{{ proposal.votes_for }}% For
</div>
<div class="progress-bar progress-bar-danger" style="width: {{ proposal.votes_against }}%">
<span class="sr-only">10% Complete (danger)</span>
{{ proposal.votes_against }}% Against
</div>
</div>
<p><a class="btn btn-primary btn-lg" href="#" role="button">Learn more</a></p>
</div>
If you just want to go to the Proposal details you should definitely look to a class-based DetailView.
You can make it with AJAX request or you can make it with form. For the both of types you should have a View to catch it.
HTML Form:
In your template you should have:
<form id="formId" method="post" action="{% url 'catch-proposal' %}">
{% csrf_token %}
<input type="hidden" name="proposal_id" value="{{ proposal.id }}"/>
<p><button type="submit" class="btn btn-primary btn-lg">Learn more</a></p>
<!-- <input type="submit" class="btn btn-primary btn-lg" value="Learn more"/> -->
</form>
It will go to your View from urls.py:
url(r'^post/for/proposal/$', catch_proposal, name='catch-proposal'),
# if your view class-based
# url(r'^post/for/proposal/$', CatchProposal.as_view(), name='catch-proposal')
Then in your view you will catch POST data:
def catch_proposal(request):
if request.method == "POST":
print(request.POST) # have a look for your post params
return reverse_lazy('index') # your response, you can make it on your own
AJAX:
Check it! AJAX and Django
Page uses AJAX without any HTML form
A page makes a POST request via AJAX, and the page does not have an HTML form with a csrf_token that would cause the required CSRF cookie to be sent.
Solution: use ensure_csrf_cookie() on the view that sends the page.
In your scripts define:
function sendPost(proposalId) {
$.ajax({
url: '{% url 'catch-proposal' %}', // or just /ajax/catch/proposal/
method : "POST",
data: {
// your data to send key => val
'id': proposalId
},
dataType: 'json', // it can be xml, json, script, html
success: function (result) {
// Do something if your request was successful (code=200)
// All response data stored in result
console.log(result)
},
error : function(xhr,errmsg,err) {
// Error case
console.log(xhr.status + ": " + xhr.responseText);
}
});
}
For your Learn More button:
<p><button class="btn btn-primary btn-lg" role="button" onclick="sendPost({{ proposal.id }})">Learn more</button></p>
And you will catch it in your View:
#ensure_csrf_cookie # Since you sending POST request without form tag
def catch_proposal(request):
response_data = {} # your response
if request.method == 'POST':
# your post request
if 'id' not in request.POST: # check the param from POST
# Provide error message
response_data['error_message'] = "Can't find ID in POST params..."
else:
# Do whatever
proposal_id = int(request.POST.get('id'))
try:
proposal = Proposal.objects.get(id=transport_id)
response_data['success'] = True
except Proposal.DoesNotExist:
response_data['success'] = False
return JsonResponse(response_data)
else:
response_data = {
'error_message': 'Something is going very strange and wrong...'
}
return JsonResponse(response_data)
Adding created View to urls.py:
from .views import catch_proposal # or yourapp.views
....
url(r'^ajax/catch/proposal/$', catch_proposal, name='catch_proposal'),
....

Categories

Resources