Django/Ajax/Jquery running two ajax requests in the same event. - javascript

I think I'm really close to getting this working but I need some help with the Jquery as everything works as intended on the second click and beyond. It just doesn't work on the first click.
I'm basically trying to replicate the youtube like and dislike buttons. So you click the thumbs up, it shows +1 and if you click it again it subtracts one. All that logic works until I get into the AJAX and Jquery portion.
I have one ajax request that adds the user to the "liked" ManyToManyField. Then I have one apiview that I'm connecting to just produce the upvote and downvote count, then displaying that into the template.
This all works, but again the first click produces the correct result in the console. The second click produces the "opposite" result in the template and correct result in the console. Then of course if I reload every time I click "up" it works as intended but i'm trying to prevent reloading.
template - Jquery/Ajax
$(".upvote-btn").click(function(e){
e.preventDefault()
var this_ = $(this)
var upvoteToggleUrl = this_.attr("data-href")
var voteCountAPIUrl = "{% url 'streams:vote-count' streampost.pk %}";
$.ajax({
url: upvoteToggleUrl,
method: 'GET',
data: {},
success: function(data){
}, error: function(error){
console.log(error)
console.log("error")
}
})
$.ajax({
url: voteCountAPIUrl,
method: 'GET',
data: {},
success: function(data){
console.log(data.upvotes)
console.log(data.downvotes)
$('.upvote-count').text(data.upvotes);
}, error: function(error){
console.log(error)
console.log("error")
}
})
})
HTML
<p>
Upvotes
<div class="upvote-count" data-href="{% url 'streams:vote-count' streampost.pk %}">
{{ streampost.upvotes.count }}
</div>
<a class="upvote-btn" data-href='{{ streampost.get_api_upvote_url }}'
href='{{ streampost.get_upvote_url }}'>Up</a>
Downvotes {{ streampost.downvotes.count }}
</p>

It seems to me like you want the upvote request to complete first before you retrieve the upvote count. To do that, you need to make the second request in the callback of the first:
$(".upvote-btn").click(function(e){
e.preventDefault()
var this_ = $(this)
var upvoteToggleUrl = this_.attr("data-href")
var voteCountAPIUrl = "{% url 'streams:vote-count' streampost.pk %}";
$.ajax({
url: upvoteToggleUrl,
method: 'GET',
data: {},
success: function(data){
$.ajax({
url: voteCountAPIUrl,
method: 'GET',
data: {},
success: function(data){
console.log(data.upvotes)
console.log(data.downvotes)
$('.upvote-count').text(data.upvotes);
}, error: function(error){
console.log(error)
console.log("error")
}
})
}, error: function(error){
console.log(error)
console.log("error")
}
})
})

Related

How to pass the id of the element user clicked on back to Flask using AJAX

I am trying to work on this website that shows a list of records, and when a user clicks on one of them, he will be navigated to another page that shows the details of the record. The logic behind it is, each 'li' tag has an "id" attribute that is unique, and I can use that id to call API and fetch the detailed info for that record. However, it seems that nothing was passed back to Flask...
HTML code:
<ul class="list-group list-group-flush">
{%for i in range(0,length)%}
<li class="list-group-item" id={{res.value[i].id}}>
<h4 class="itemName">Name:{{res.value[i].name}}</h4>
<p class="itemAssetType">{{res.value[i].assetTypes[0]}}</p>
<p class="itemQualifiedName">{{res.value[i].qualifiedName}}</p>
</li>
{%endfor%}
</ul>
JavaScript code:
$(function(){
$('li').click(function(){
var elementID = this.id
var datatosend = JSON.stringify({"guid":elementID})
$.ajax({
url: '/details',
data: datatosend,
type: 'POST',
success: function(response){
window.location.href = '/details'
console.log(response); //for stackoverflow: this shows None in console
},
error: function(ts) { alert(ts.responseText) }
});
});
});
Flask code:
#app.route('/details',methods=['POST','GET'])
def details():
print (request.json) #this gives: None
print (request.data) #this gives: b''
print (request.args.get("guid")) #this gives: None
return str(request.json)
Just wondering how am I supposed to pass that id into flask?? Why is it always empty???
I am kinda new to the front end, any help is greatly appreciated.
i think you remove this part
success: function(response){
window.location.href = '/details'
console.log(response);
}
because you get some data from server and then you go another page? but your data still stands in previous page!
You need to keep stay in current page and use your data like this:
success: function(response){
console.log(response);
}
$(function () {
$('li').click(function () {
var elementID = this.id;
console.log(this.id)//for stackoverflow: this shows the id as I expected
$.ajax({
url: '/details',
data: { guid: this.id },
type: 'POST',
success: function (response) {
console.log(response);
},
error: function (error) {
console.log('failed');
console.log(error);
console.log('element id =======>',elementID)//it is work now!!!
}
});
});
});
<script src="https://cdnjs.cloudflare.com/ajax/libs/jquery/3.3.1/jquery.min.js"></script>
<li id="xyz">##click me##</li>
<script src="app.js"></script>

Refresh content in a for loop using jquery in Django

I am creating a website that allows users to search for a list of papers. Once a list of papers is returned, the user can click "like" or "dislike" to one or more papers. The like count should dynamically update as the user click the like button.
I am using jquery to handle the dynamic update of the like count. However, I am not sure how to tell the success function in the ajax WHICH id to update. The reason is that the id is generated on the fly, and it is determined by which papers are returned as search results to the user.
So far, I have the following in the template:
{% for result in results %}
<li >
{{ result.title}},
<span class="like_span fa fa-thumbs-up"></span>
<strong id="like_count_{{ result.pk }}">{{result.likes}} </strong>
</li>
{% endfor %}
As you can see, i specify the id of the part where I want the dynamic update to happen as "like_count_{{ result.pk }}". I am not sure if this is the best way to go about it.
The jquery part looks like this:
<script>
$(document).ready(function(){
$(".like_button").click(function(){
$.ajax({
type: "GET",
data: {'pk': $(this).data('pid'),
'liked': $("span").hasClass('fa fa-thumbs-up') },
url: "{% url 'search:paperpreference' %}",
success: function(response) {
var pk = $(this).data('pid');
$(?????).html(response.likes )
},
error: function(response, error) {
alert(error);
}
});
});
});
</script>
Simply put, I don't know how can i specify the ????? part such that when success, the new like count is only updated to that specific paper, not the first paper in the loop.
The views.py has the following so far:
def paperpreference(request):
# if request.method == "GET":
pid = request.GET['pk']
paper = Paper.objects.get(pk=pid)
likes = paper.likes + 1
paper.likes = likes
paper.save()
data = {'likes': paper.likes}
return JsonResponse(data)
I am new to Jquery, any help would be much appreciated!
Thanks to suggestions by #dirkgroten, the like count can now be dynamically updated by the following jquery function. The trick is to move the pk declaration to before the ajax.
<script>
$(document).ready(function(){
$(".like_button").click(function(){
var pk = $(this).data('pid')
$.ajax({
type: "GET",
data: {'pk': pk,
'liked': $("span").hasClass('fa fa-thumbs-up') },
url: "{% url 'search:paperpreference' %}",
success: function(response) {
$("#like_count_"+ pk).html(response.likes )
},
error: function(response, error) {
alert(error);
}
});
});
});
</script>
another option is return the id from the server.
def paperpreference(request):
# if request.method == "GET":
pid = request.GET['pk']
paper = Paper.objects.get(pk=pid)
likes = paper.likes + 1
paper.likes = likes
paper.save()
data = {'likes': paper.likes,'pid':pid}
return JsonResponse(data)
<script>
$(document).ready(function(){
$(".like_button").click(function(){
var pk = $(this).data('pid')
$.ajax({
type: "GET",
data: {'pk': pk,
'liked': $("span").hasClass('fa fa-thumbs-up') },
url: "{% url 'search:paperpreference' %}",
success: function(response) {
$("#like_count_"+ response.pid).html(response.likes )
},
error: function(response, error) {
alert(error);
}
});
});
});
</script>

Ajax wait till redirect to finish executing.

I have basically the same problem as the one described in the link below, but I dont find the solution to be very clear. I want my ajax success function to wait until the window function is finished executing, THEN modify the divs. Instead, it modifies the divs of the current page, then redirects. AJAX: on success redirect then modify new page
main.js
$("#form").submit( function(e) {
e.preventDefault();
var id = $('#searchbar').val(); // store the form's data.
$.ajax({
url: '/search',
type: 'POST',
data: {id:id},
dataType: 'text',
success: function(data) {
//Redirect to the page where we want to display the data
window.location.href = '/test';
data = JSON.parse(data);
console.log(data);
$("#count").text("we analyzed...");
$("#result1").text(data.county);
$("#totals").text("with a score of..");
$("#result2").text(data.totalSentiments);
},
error: function(jqXHR, textStatus, errorThrown){
console.log("error")
alert(textStatus, errorThrown);
}
});
});
I Will Suggest you Javascript Local Storage .
main.js
$("#form").submit( function(e) {
e.preventDefault();
var id = $('#searchbar').val(); // store the form's data.
$.ajax({
url: '/search',
type: 'POST',
data: {id:id},
dataType: 'text',
success: function(data) {
//Redirect to the page where we want to display the data
window.location.href = '/test';
data = JSON.parse(data);
console.log(data);
// Store
localStorage.setItem("count", "we analyzed...");
localStorage.setItem("result1", data.county);
localStorage.setItem("totals", "with a score of..");
localStorage.setItem("result2", data.totalSentiments);
},
error: function(jqXHR, textStatus, errorThrown){
console.log("error")
alert(textStatus, errorThrown);
}
});
});
On Ready on same page:
jQuery(document).ready(function(){
if (localStorage.count) {
$("#count").text(localStorage.count);
}
if (localStorage.result1) {
$("#result1").text(localStorage.result1);
}
if (localStorage.totals) {
$("#totals").text(localStorage.totals);
}
if (localStorage.result2) {
$("#result2").text(localStorage.result2);
}
});
Local Storage Store Data in Browser Storage. You Also Can Remove Data From Local Storage.
setting the value of location.href will cause a full page refresh.
Therefore all your scripts will be wiped out.
If you REALLY wants to use the result of a ajax call to a redirected page, you should store this response data somewhere, then reuse it on your new page.
//save "data" in localSotorage
localStorage.myAjaxResponse = data; //if data is JSON then use: JSON.stringify(data) instead.
Then on your "/test" page, create a script to check for the value on the localStorage then display it.
data = JSON.parse(localStorage.myAjaxResponse);
console.log(data);
$("#count").text("we analyzed...");
$("#result1").text(data.county);
$("#totals").text("with a score of..");
$("#result2").text(data.totalSentiments);
Although, there are other better ways to accomplish what you want.
You can do something like this:
On your ajax success:
data = JSON.parse(data);
console.log(data);
window.location.href = '/test?county='+data.county+'&sentiment='+totalSentiments;
Then on your test page write in javascript block:
var params={};
window.location.search
.replace(/[?&]+([^=&]+)=([^&]*)/gi, function(str,key,value) {
params[key] = value;
}
);
if (params.length > 0) {
$("#count").text("we analyzed...");
$("#result1").text(params['county']);
$("#totals").text("with a score of..");
$("#result2").text(params['sentiments']);
}

jquery function not redirecting url

I am working with codeigniter and jquery. I am using ajax to send some info to a codeigniter function to perform a db operation , in order to update the page. After the operation is complete I am trying to refresh the page. However the refresh works inconsistently and usually I have to reload the page manually. I see no errors in firebug:
var message = $('#send_message').val()
if ((searchIDs).length>0){
alert("searchIDs "+searchIDs );
$.ajax({
type: "POST",
url: "AjaxController/update",
data:{ i : searchIDs, m : message },
dataType: 'json',
success: function(){
alert("OK");
},
complete: function() {
location.href = "pan_controller/my_detail";
}
})
.done(function() { // echo url in "/path/to/file" url
// redirecting here if done
alert("OK");
location.href = "pan_controller/my_detail";
});
} else { alert("nothing checked") }
break;
How can I fix this?
addendum: I tried changing to ;
$.ajax({
type: "POST",
url: "AjaxController/update",
data:{ i : searchIDs, m : message },
dataType: 'json',
.done(function() { // echo url in "/path/to/file" url
// redirecting here if done
alert("REFRESHING..");
location.href = "pan_controller/my_detail";
});
}
})
This is just defaulting to the website homepage. again, no errors in firebug
Add the window object on location.href like this:
window.location.href = "pan_controller/my_detail";
Try to use full path like
$.ajax({a
type: "POST",
url: "YOURBASEPATH/AjaxController/update",
data:{ i : searchIDs, m : message },
dataType: 'json',
.done(function() { // echo url in "/path/to/file" url
// redirecting here if done
alert("REFRESHING..");
location.href = "YOURBASEPATH/pan_controller/my_detail";
});
}
})
BASEPATH should be like this "http://www.example.com"
Try disabling the csrf_enabled (config/config.php) and trying it. If that works, then re-enable the protection and, instead of compiling data yourself, serialize the form; or, at least include the csrf hidden field codeigniter automatically adds. You can also use GET to avoid the CSRF protection, but that's least advisable of of the solutions.

Django url rewrites and passing a parameter from Javascript

As a bit of a followup question to my previous , I need to pass a parameter to a view. This parameter is not known until the JS executes.
In my URLConf:
url(r'^person/device/program/oneday/(?P<meter_id>\d+)/(?P<day_of_the_week>\w+)/$',
therm_control.Get_One_Day_Of_Current_Thermostat_Schedule.as_view(),
name="one-day-url"),
I can pass it this URL and it works great! ( thanks to you guys).
http://127.0.0.1:8000/personview/person/device/program/oneday/149778/Monday/
In My template I have this:
var one_day_url = "{% url personview:one-day-url meter_id=meter_id day_of_the_week='Monday' %}";
In my javascript:
$.ajax({
type: 'GET',
url: one_day_url ,
dataType: "json",
timeout: 30000,
beforeSend: beforeSendCallback,
success: successCallback,
error: errorCallback,
complete: completeCallback
});
When this triggers it works fine except I dont necessarily want Monday all the time.
If I change the javascript to this:
var one_day_url = "{% url personview:one-day-url meter_id=meter_id %}";
and then
$.ajax({
type: 'GET',
url: one_day_url + '/Monday/',
dataType: "json",
timeout: 30000,
beforeSend: beforeSendCallback,
success: successCallback,
error: errorCallback,
complete: completeCallback
});
I get the Caught NoReverseMatch while rendering error. I assume because the URLconf still wants to rewrite to include the ?P\w+) .
I seems like if I change the URL conf that breaks the abailty to find the view , and if I do what I do above it gives me the NoREverseMatch error.
Any guidance would be appreciated.
I usually do something along the lines of
var one_day_url = "{% url personview:one-day-url meter_id=meter_id day_of_the_week='REPLACE_ME' %}";
// ...
url: one_day_url.replace('REPLACE_ME', 'Sunday')
you may want to use this kind of project which is meant to answer to this precise question...
notice: it may help hacker to map the website:
https://github.com/Dimitri-Gnidash/django-js-utils
When I don't use this project I put a default value in the url and replace it by correct value.
so use a complete reverse then:
url: one_day_url.replace('/Monday/','/Caturday/')
and even if you replace monday by monday it will works...
note: this ugly haks will fail if your default value is already sooner in the url so use it consequently.
Why not just pass them in as part of the request data. You can use the jQuery get function and pass them in as paramaters.
$.get("{%url personview%}", {'meter_id':"meter_id", "day_of_the_week":"monday" ...}, function(){do stuff when info is returned});
Then in your view you can do:
meter = request.GET['meter_id']
This will allow you to use it in your view.
I had a similar question. I wanted to open a URL when someone clicked a button. For what it's worth, here is how I handled this situation.
Define the URL as an attribute:
{% for article in articles %}
<button data-article-url="{% url view_article article.id %}">
Read Article #{{ article.id }}
</button>
{% endfor %}
Using jQuery, read the attribute and carry on:
var article_url = $(this).attr("data-article-url");
$.ajax({
url: article_url,
...
});
You could use tokens in your url and pass it as a variable to your module:
<script src="{{ STATIC_URL }}js/my-module.js"></script>
<script>
$(function(){
MyModule.init(
"{% url personview:one-day-url meter_id='0000' day_of_the_week='{day}' %}"
);
});
</script>
// js/my-module.js
var MyModule = {
init: function(one_day_url) {
var id = 1, day = 'Saturday';
this._one_day_url = one_day_url;
console.log(this.one_day_url(id, day));
$.ajax({
type: 'GET',
url: this.one_day_url(id, day),
dataType: "json",
timeout: 30000,
beforeSend: beforeSendCallback,
success: successCallback,
error: errorCallback,
complete: completeCallback
});
},
one_day_url: function(meter_id, day) {
return this._one_day_url.replace('0000', meter_id).replace('{day}', day);
}
};
Notice that token should match the regex type to resolve successfully (I can't use {meter_id} because it's defined with \d+).
I'm a little bit unsatisfied with this solution and I ended by writing my own application to handle javascript with django: django.js. With this application, I can do:
{% load js %}
{% django_js %}
{% js "js/my-module.js" %}
// js/my-module.js
var MyModule = {
init: function() {
var id = 1, day = 'Saturday';
console.log(
Django.url('personview:one-day-url', id, day),
Django.url('personview:one-day-url', [id, day]),
Django.url('personview:one-day-url', {
meter_id: id,
day_of_week: day
})
);
$.ajax({
type: 'GET',
url: Django.url('personview:one-day-url', id, day),
dataType: "json",
timeout: 30000,
beforeSend: beforeSendCallback,
success: successCallback,
error: errorCallback,
complete: completeCallback
});
}
};
$(function(){
MyModule.init();
});

Categories

Resources