Looking to rename Django Ajax "like" button, but not working - javascript

Currently my button functions, but I've placed it inside of a django for loop. I'd like to move the js logic to a separate file, but first I need to give it a better name. Here is a snippet of my code:
{% for post in posts %}
.....
<script type="text/javascript">
function toggleLike{{post.id}}(){
$.ajax({
url: "{% url 'photo_blog-post_like_api' post.id %}",
success: function(data) {
$("#likeCount{{post.id}}").html(data.like_count + ' likes');
$('#imageElement{{post.id}}').html(data.img);
}
});
};
</script>
<a id=imageElement{{post.id}} onclick="toggleLike{{post.id}}()"><img src="/media/nav_buttons/liked.svg" height="17" width="17"></a>
....
<post info here>
....
{% endfor %}
When I remove the {{post.id}} from the function name, and onclick call, the button only functions for the post on the bottom of the page. All of the other buttons toggle the information for that one post. How can I give this function a general name, but still have it interact uniquely with each post?

You shouldn't be doing this as part of the name anyway. The post id is a parameter. The only collocated part is working out how to pass it to the Django URL tag
function toggleLike(post_id){
$.ajax({
url: "{% url 'photo_blog-post_like_api' "00000" %}".replace("00000", post_id)
success: function(data) {
$("#likeCount" + post_id).html(data.like_count + ' likes');
$('#imageElement' + post.id).html(data.img);
}
});
};
</script>
<a id=imageElement{{post.id}} onclick="toggleLike({{post.id}})"><img src="/media/nav_buttons/liked.svg" height="17" width="17">

Related

Django json response stay in the same page

I'm making a like button for a post in django. What I need is that when the like button is clicked, the function is executed, but I need the page not to be reloaded (To later use javascript). To do that I return a jsonresponse() instead of a return render. But the real problem is that it redirects me to the page that I show in the photo. The page is not reloaded. as I want it. but I don't want it to show me the blank page with the jsonresponse data (like this photo).I want to stay in the same page without reload.
My view function:
def liking (request, pk):
posts = get_object_or_404(Post, id = pk)
if request.user in posts.likes.all():
posts.likes.remove(request.user)
else:
posts.likes.add(request.user.id)
likes_count = posts.likes.all().count()
print(f'likes_count = {likes_count}')
data= {
'likes_count': likes_count,
}
#return redirect ('index')# This is commented
return JsonResponse(data, safe=False, status=200 )
You can use AJAX. Simply place the code below in the template and trigger it with buttons.
<script src="https://ajax.googleapis.com/ajax/libs/jquery/3.6.1/jquery.min.js"></script>
<script>
function get_likes(pk){
$.ajax({
url: '{% url "url-name" pk %}',
type: 'GET',
success: function (res) {
var likes = JSON.parse(res);
return likes["likes_count"]
}
});
}
</script>
If you need to post any data, you can use the lines below.
function get_likes(pk){
$.ajax({
url: '{% url "url-name" pk %}',
type: 'POST',
data: {
csrfmiddlewaretoken: "{{ csrf_token }}",
data1:"data",
data2:"data"
},
success: function (res) {
var likes = JSON.parse(res);
return likes["likes_count"]
}
});
}
You can add the following lines in your function to use the posted data on the django side.
data1 = request.POST.get("data1")
data2 = request.POST.get("data2")
After trying for a while, I found the problem. It had nothing to do with the ajax request or a fetch, which is what I ended up using. It was simply that I had the url of the views.py function in the href="" and for this reason the white screen came out with the jsonresponse() data:
I had to change:
<a class="btn btn-dark like" id="like_button" href="{% url 'liking' post.id %}"> Like</a>
So:
<a class="btn btn-dark like" id="like_button" href="#"> Like</a>
Thanks for all the answers!

Is there a way to replace an HTML variable with a Javascript variable?

So I have this variable called "posts" in html and its used in a for loop to create a series of well, posts.
{% for post in posts %}
{% with voteform = voteform, votes = votes, post = post %}
{%include "postlayout.html"%}
{% endwith %}
{% endfor %}
</div>
I then use Ajax to retrieve a new querylist from flask and return another series of posts based on what filters the user selects.
$('input[type=checkbox]:checked').each(function(){
all.push($(this).val());
});
console.log(all)
var moods = {
'filters': all
};
$.ajax({
url : "/update",
type: 'POST',
data: JSON.stringify(moods),
contentType: 'application/json;charset=UTF-8',
success: function(resp){
$('div#response').html('posts <br>')
for (var key in resp.data) {
var val = resp.data[key]
console.log(val)
$('div#response').append(resp.data[key]['songname'] + ' by ' +
resp.data[key]['artist'] + '<br>')
}
console.log(resp.data)
},
error: function(error){
console.log(error)
}
});
}
So I was wondering if there was a way to replace "posts" in my html code with "resp.data" from my json code.
Unfortunately, no.
The Flask template is rendered into HTML server-side before the AJAX request is made and so you cant use the AJAX response in your Flask template.
You'll have to use JavaScript (or/and jQuery) to loop over the response data and insert the required HTML.

My AJAX is working and I want to know why

In my app I made a favorite list that a user can populate using AJAX.
Is it working perfectly but I am not sure if I did it the right way and I would like to know how to do it the proper way. Or maybe somehow I did it right.
My html:
<div class='sub_button'>
<form class="add_btn" method='post'>{% csrf_token %}
<button class='added btn' value= '{{product.id }} {{ sub_product.id }}' ><i class=' fas fa-save'></i></button>
</div>
My AJAX:
$(".row").on('click', ".added", function(event) {
let addedBtn = $(this);
console.log(addedBtn)
event.preventDefault();
var product = $(this).val();
var url = '/finder/add/';
$.ajax({
url: url,
type: "POST",
data:{
'product': product,
'csrfmiddlewaretoken': $('input[name=csrfmiddlewaretoken]').val()
},
datatype:'json',
success: function(data) {
if (data['success'])
addedBtn.hide();
}
});
});
My views.py
def add(request):
data = {'success': False}
if request.method=='POST':
product = request.POST.get('product')
user = request.user
splitted = product.split(' ')
sub_product = Product.objects.get(pk=(splitted[1]))
original_product = Product.objects.get(pk=(splitted[0]))
p = SavedProduct(username= user, sub_product=sub_product, original_product = original_product)
p.save()
data['success'] = True
return JsonResponse(data)
What is bugging me is the way I passed '{{product.id }} {{ sub_product.id }}'. Because I've made it after some tinkering.
There is a better way to do this.
ie, if you have only one product.id and sub_product.id in this page instance. Then in a script tag at the end of the HTML template for this page you add the following:
<script>
var product_id = {{ product.id }}
var sub_product_id = {{ sub_product.id }}
</script>
Then you can link the external JS file in which you have AJAX to this HTML template with another script tag.
Now your product_id and sub_product_id will be available in your external JS script file in which you have the AJAX code.
So that way, you don't have to pass it through the value attribute of the button tag and things look more clean.

Hide a button in jQuery after an AJAX call [duplicate]

This question already has answers here:
$(this) inside of AJAX success not working
(2 answers)
Closed 2 years ago.
enter code hereI have a list of items from a database displayed thanks to a for-loop in Django.
I have a "save button" next to each one to save them to a favorite database thanks to an AJAX call. Everything works like a charm.
But I want the "save button" to .hide() whenever the AJAX call is a "success". But if I do so, every "save button" from the page is hidden.
So I tried to use .parent() or .closest() to select only the <div> where my "save is button" with no luck.
My HTML:
{% for sub_product in products %}
<div class='sub_button'>
<form class="add_btn" method='post'>{% csrf_token %}
<button class='added btn' value= '{{product.id }} {{ sub_product.id }}' ><i class=' fas fa-save'></i></button>
</div>
{% endfor %}
My AJAX:
$(".added").on('click', function(event) {
event.preventDefault();
var product = $(this).val();
var url = '/finder/add/';
$.ajax({
url: url,
type: "POST",
data:{
'product': product,
'csrfmiddlewaretoken': $('input[name=csrfmiddlewaretoken]').val()
},
datatype:'json',
success: function(data) {
if (data['success'])
$(this).parent('.sub_button').hide();
}
});
});
Your code failing because you are in different scope, $(this) will refer to the success function you are calling, not the element clicked, you should have a reference to the button once you execute the click event listener, the following should work for you:
$(".added").on('click', function(event) {
let addedBtn = $(this); // Here is a reference
event.preventDefault();
var product = $(this).val();
var url = '/finder/add/';
$.ajax({
url: url,
type: "POST",
data:{
'product': product,
'csrfmiddlewaretoken': $('input[name=csrfmiddlewaretoken]').val()
},
datatype:'json',
success: function(data) {
if (data['success'])
addedBtn.parent('.sub_button').hide();
}
});
});

AJAX JSON response doesn't refresh for tag at Django template

I have built a view in views.py that returns a JSON when user press a button. The page updates simple html divs (last_bid, credits, message) without reloading but I have some {% for %} tags that don't refresh although JSON response is updated with extra data.
template.html script
<script>
$('#bid').on('submit', function(event){
event.preventDefault();
$.ajax({
method: 'POST',
url: '{% some url %}',
datatype: 'json',
data: {
some data
},
success: function(data) {
$('#last-bid').html(data.last_bid);
$('#credits').html(data.credits);
$('#message').html(data.message);
$('#registered_players').html(data.registered_players);
}
});
});
template.html
<div id="registered_players">
{% for i in registered_players %}
{{ i.auction_player__user__username }}
{% endfor %}
</div>
JSON
{"registered_players": [{"auction_player__user__username": "admin"}, {"auction_player__user__username": "minos"}], "last_bid": "8.10", "credits": 612, "message": ""}
Instead of targeting the div "registered_players". Either you need to loop through your JSON data and replace every single player Or you need to remove the old players html and add your new HTML.
Please provide your HTML by inspecting the html page for more clear answer.
Thank you all for the help. Managed to solve this by looping through JSON response.
var player_list = "<ul>";
for (var i=0; i< data.registered_players.length; i++){
player_list += "<li>" + data.registered_players[i].auction_player__user__username + "</li>";
}
player_list += "</ul>"
$('#registered_players').html(player_list);

Categories