django with ajax like and unlike - javascript

I , so I wrote an application with django and implemented a like and unlike function but I noticed that it works fine but the problem is if a user likes a post and decides to unlike it , the likes . count would go to -1 instead of 0 and thus it is possible for a two users like to become 3 but if one of the two unlikes it then it goes to 1 . below is my jQuery function
jQuery
$(document).ready(function(){
function updateText(btn, newCount, verb){
btn.text(newCount + " " + verb)
}
$(".like-btn").click(function(e){
e.preventDefault()
var this_ = $(this)
var likeUrl = this_.attr("data-href")
var likeCount = parseInt(this_.attr("data-likes")) | 0
var addLike = likeCount + 1
var removeLike = likeCount - 1
if (likeUrl){
$.ajax({
url: likeUrl,
method: "GET",
data: {},
success: function(data){
console.log(data)
var newLikes;
if (data.liked){
updateText(this_, addLike, "Unlike")
} else {
updateText(this_, removeLike, "Like")
// remove one like
}
}, error: function(error){
console.log(error)
console.log("error")
}
})
}
})
})
view.html
<p><a class='like-btn' data-href='{{ obj.get_api_like_url }}' data-likes='{{ obj.likes.count }}' href='{{ obj.get_like_url }}'>{{ obj.likes.count }} Like</a></p>
View.py
from rest_framework.views import APIView
from rest_framework.response import Response
from rest_framework import authentication, permissions
class PostLikeAPIToggle(APIView):
authentication_classes = (authentication.SessionAuthentication,)
permission_classes = (permissions.IsAuthenticated,)
def get(self, request, slug=None, format=None):
# slug = self.kwargs.get("slug")
obj = get_object_or_404(Post, slug=slug)
url_ = obj.get_absolute_url()
user = self.request.user
updated = False
liked = False
if user.is_authenticated():
if user in obj.likes.all():
liked = False
obj.likes.remove(user)
else:
liked = True
obj.likes.add(user)
updated = True
data = {
"updated": updated,
"liked": liked
}
return Response(data)
if any other part of my code is required I would gladly supply it. Thanks

You haven't updated the data-likes when the user has liked or unliked a post. Since, the page won't refresh the tag containing attribute data-likes with value {{ obj.likes.count }} will never re-render on UI.
if (data.liked) {
// ...
} else {
// ...
}
// update the `data-likes`
this_.data('likes', likeCount);
Note: You can use .data() method to access the data-* attributes, rather than using attr.
Ref: jQuery .data() docs

Related

How to update a value in database after n seconds of query made? Django

I have a model in which I created a field "bargain price " as shown in Models.py:
class Item(models.Model):
title = models.CharField(max_length=100)
price = models.FloatField()
bargainprice = models.FloatField(default=0)
somewhere in my template I take input from user and update the bargain price using ajax as shown below:
$.ajax({
url: "/bargain/" + id + "/",
data: { csrfmiddlewaretoken: window.CSRF_TOKEN, 'input': parseFloat(input) },
type: 'POST'
}).done(function (response) {
alert(response);
});
and I successfully update the price by the view:
def Bargain(request, uid):
if request.method == 'POST':
item = Item.objects.get(id=uid)
item.bargainprice = request.POST['input']
item.save()
message = 'update successful'
return HttpResponse(message)
else:
return HttpResponse("this is not working..")
**Now what I want. I want to reset this Bargain_price updated value to default after n seconds **
Can anyone suggest to me the method to do it? Thanks in advance.

How to call Django API with Javascript with Authenticated user in Django

I'm using Django for Backend, PostgresSQL as DB and HTML, CSS and Javascript as Frontend. I am calling Django API via Javascript. Where user is adding a product to a cart, and I'm calling the cart with DRF to show all the data to the user. But problem is that, user can see all the data of other user. So, how can authenticated user can see his/her selected product on a cart.
Here is a detailed code:
views.py
adding product to cart
def addProduct(request):
user = request.user
product_id = request.GET.get('product_id')
product_cart = Product.objects.get(id=product_id)
Cart(user=user, product=product_cart).save()
return render(request, 'cart/addtocart.html')
Api View (views.py)
#api_view(['GET'])
def showproduct(request):
if request.method == 'GET':
result = Cart.objects.all()
serialize = productserializers(result, many = True)
return Response(serialize.data)
serializer.py
from .models import *
from rest_framework import serializers
class productserializers(serializers.ModelSerializer):
class Meta:
model = Cart
fields = '__all__'
depth = 1
Javascript to call Django API
$(document).ready(function() {
$.ajax({
url: 'http://127.0.0.1:8000/showproduct/',
dataType: 'JSON',
success: function(data){
for (var i = 0; i < data.length; i++)
{
var row =
$('<tr> .. ..........</tr>');
$("#table").append(row);
}
}
});
});
NOW, How to show the specific user(authenticated user) there specific cart item.
you have to pass user id when you are calling ajax.
If you are using GETmethod than pass user id in URL and access it via argument in your view for eg.
$(document).ready(function() {
$.ajax({
url: '{% url "showdata" %}',
dataType: 'JSON',
success: function(data){
for (var i = 0; i < data.length; i++)
{
var row =
$('<tr> .. ..........</tr>');
$("#table").append(row);
}
}
});
});
and in your views.py
#api_view(['GET'])
def showproduct(request):
if request.method == 'GET':
result = Cart.objects.filter(user=request.user)
serialize = productserializers(result, many = True)
return Response(serialize.data)
and add this in your urls.py
urlpatterns = [
path("showdata/", views.showproduct, name='showdata')
]
UPDATE
there is no need to pass user id in ajax URL if user is authenticated than user will come in request
so please change you views.py, urls.py and ajax URL.

Bad request error in Flask while request names generated with javascript

I'm creating an app to calculate a projection of the transit given the years and some other values, first I created a script in javascript where depending on if the user decide to add a new type of vehicle a new div is created with unique ids and names and ofcourse the data the user introduced, for showing the final result i'm using ajax, the problem comes when i tried to access the data via flask, i'm getting a bad request from the names of each vehicle like if they did not exist, but the page is actually displaying them (hope you understand my english and my problem :) )
I've tried giving a specific name (a1) an then tried to take the value in flask but i still can#t make it work.
Python
#app.route("/pavimentos/calculoTransito" , methods=['POST'])
def calculoTransito():
direc = float(request.form["direc"])
zr = float(request.form["zr"])
years = float(request.form["years"])
tc = float(request.form["direc"])
vehicles = int(request.form["vehicles"])
car1 = request.form.get("a1", None)
if car1==None:
print("No funciona")
else:
print("Funciona")
always get "No funciona"
Javascript
countClicks = 0
lista_vehiculos = []
function addVehicle(){
countClicks += 1;
//var automovil = document.getElementById("automovil").value
var fd = document.getElementById("damage_factor").value
var currentType = document.getElementById("vehicleType")
if(currentType.value == 1){
var icon = "<h2 class='pt-4'><i class='fas fa-car text-secondary'></i></h2>";
var tipoVehiculo = "Automóvil";
}
... More code for select the currentType ...
var vehicleStyle = "<div><input id=a" + countClicks + "name=a" + countClicks + "value=" + fd + "></div>"
lista_vehiculos.push(vehicleStyle)
var vehicle = document.getElementById("vehiclesContainer").innerHTML += lista_vehiculos[countClicks-1]
document.getElementById("vehicles").value = countClicks
}
AJAX part
$(document).ready(function(){
$('form').on('submit', function(event){
$.ajax({
data:{
direc: $('#direc').val(),
zr: $('#zr').val(),
years: $('#years').val(),
tc: $('#growingRate').val(),
vehicles: $('#vehicles').val(),
car1: $('#a1').val()
},
type: 'POST',
url: '/pavimentos/calculoTransito'
})
.done(function(data){
if (data.resultado){
$('#resultado').text(data.resultado).show()
}
})
event.preventDefault();
});
});
You're not submitting a form, you're sending JSON. The initial event might be the submission of a form, but your AJAX uses event.preventDefault() and does not end up submitting a traditional serialized form. You can't use car1 = request.form.get("a1", None) here.
Firstly, you should correct your AJAX to add a contentType:
$(document).ready(function(){
$('form').on('submit', function(event){
$.ajax({
data: JSON.stringify({
direc: $('#direc').val(),
zr: $('#zr').val(),
years: $('#years').val(),
tc: $('#growingRate').val(),
vehicles: $('#vehicles').val(),
car1: $('#a1').val()
}),
type: 'POST',
contentType: 'application/json; charset=utf-8',
url: '/pavimentos/calculoTransito'
})
.done(function(data){
if (data.resultado){
$('#resultado').text(data.resultado).show()
}
})
event.preventDefault();
});
});
And then you need to change your Flask method from request.form to request.json. So the Flask side would look something like:
#app.route("/pavimentos/calculoTransito" , methods=['POST'])
def calculoTransito():
req = request.json
direc = float(req["direc"])
zr = float(req["zr"])
...
car1 = req.get("a1", None)
if car1 is None: # None is a singleton, you shouldn't use == here
print("No funciona")
else:
print("Funciona")
LATE EDIT
This can't work because calculoTransito does not actually return anything, so Flask will throw an error from that alone. Your view function actually has to return something other than an implicit None.

Ajax POST not sending data when calling 'request.POST' in Django view

I am attempting to get an Ajax POST to to send data to my view so I can manipulate my data there, when I click on a div with class up-arrow.
Problem is, when I click said div and print request.POST in my view file, I am getting a POST object that contains <QueryDict: {}>. Empty! I can't seem to figure out why my the POST request isn't sending my data through.
Here is my HTML...
{% for i in post.posts %}
<li>
<div>
<div class='up-arrow'>
</div>
{{i}}
</div>
</li>
{% endfor %}
Here is my AJAX/jQuery...
$(document).ready(function(){
$('.up-arrow').click(function(){
$(this).hide()
console.log('click')
$.ajax({
headers: {
'Content-Type':'application/json',
'X-CSRFToken': getCookie('csrftoken')
},
url: 'voteuppost',
type: 'POST',
data: {'dane': 123456789101112},
success: function(data) {
alert('success!')
},
error: function(){
alert('fail')
}
})
return false
});
function getCookie(name) {
var cookieValue = null;
if (document.cookie && document.cookie != '') {
var cookies = document.cookie.split(';');
for (var i = 0; i < cookies.length; i++) {
var cookie = jQuery.trim(cookies[i]);
if (cookie.substring(0, name.length + 1) == (name + '=')) {
cookieValue = decodeURIComponent(cookie.substring(name.length + 1));
break;
}
}
}
return cookieValue;
}
})
Here is my view...
class VoteUpPost(View):
def post(self, request):
print(request.POST)
return JsonResponse({'status': True})
Here is my url route...
url(r'^voteuppost$', VoteUpPost.as_view()),
Things I have tried...
1) I used GET instead of POST and I am able to get the data value using request.GET.get('dane')
1) Tried using request.POST.data and request.POST.DATA and get the following... AttributeError: 'QueryDict' object has no attribute 'data'
and I also get a 'fail' alert.
How do I send my data over to my view via a POST request and then access the data within?
When posting JSON data with application/json you need to use request.body instead of request.POST.
Like so:
class VoteUpPost(View):
def post(self, request):
print(request.body)
data = json.loads(request.body)
return JsonResponse({'status': True})
Also as Jacques mentioned, make sure to update your js to pass a JSON string.
Change:
data: {'dane': 123456789101112},
To:
data: JSON.stringify({'dane': 123456789101112}),
Django request can only parse application/x-www-form-urlencoded and
multipart/form-data to request.POST. For other content types you have to use request.body property. for assertion of content type you can get the content type from request.META.get('CONTENT_TYPE')
def sample_view(request):
if request.META.get('CONTENT-TYPE') == 'application/json':
data = json.loads(request.body)
return JsonResponse({'any-message':'Hello'})

How to run Django view function once a button is clicked in a template

I've made a webpage that displays the results of the query for concert data based on the parameters submitted by the user in a POST request through an api. Users of the web app need to be able to add the concerts to their list of concerts or to send invites to other users for a concert. This would require sending the information for each concert back to the server where it can be stored in the model for a user.
In each list element of the results list, I have two buttons that when clicked would send POST requests to the server with the concert information using an ajax call. Currently I only have the shell for these two functions as I'm not to clear on how to go about sending the data for the current list item and then initiating the corresponding function in the view. Here is what I currently have for the client side:
var venues = {{venues|safe}};
var dates = {{raw_dts|safe}};
var ticket_statuses = {{ticket_statuses|safe}};
var ticket_urls = {{ticket_urls|safe}};
console.log("length of artist list" + venues.length);
var $list = $("<ul class='list-group'>");
for(var i = 0; i < venues.length; i++){
$list.append("<li class='list-group-item'>Artist: {{form_artistSelect}} Location: " + venues[i].city + ', ' + venues[i].region +' Venue: ' + venues[i].name +
"Date: " + dates[i] + "tickets status: " + ticket_statuses[i] + "<br> ticket link " + "<button id ='invite'type='button' class='btn btn-primary-outline'>Invite a friend</button> <button id = 'save' type='button' class='btn btn-primary-outline'> Save concert</button> </li>");
}
// var $resultObj = $('<div id = "inviteObj" style="margin:100px"></div>');
// $resultObj.append($divline);
$list.appendTo($("#container"));
$("#save").click(function() {
$.ajax({
url: your_url,
method: 'POST',
data: {
name: value,
click: True
}
success:function(data){
}
});
});
$("#invite").click(function() {
$.ajax({
url: your_url,
method: 'POST',
data: {
name: value,
click: True
}
success:function(data){
}
});
});
Inside of views.py I have one view function that handles getting the JSON response and passing it to the client side based on the user input it gets from the form request. Here is the view:
def search(request):
form = SearchForm(request.POST or None)
if form.is_valid():
form_artistSelect = urllib2.quote(form.cleaned_data.get("artist_select"))
form_city = urllib2.quote(form.cleaned_data.get("city"))
form_state = urllib2.quote(form.cleaned_data.get("state"))
mile_radius = urllib2.quote(form.cleaned_data.get("radius"))
#print "testing"
url = "http://api.bandsintown.com/events/search?artists[]=" + form_artistSelect + "&location=" +form_city+","+ form_state+"&radius="+ mile_radius + "&format=json&app_id=YOUR_APP_ID"
data = json.load(urllib2.urlopen(url))
#titles = [ i.get("title") for i in data]
raw_dts = json.dumps([i.get("datetime") for i in data])
#formatted_dts = [i.get("formatted_datetime") for i in data]
ticket_urls = json.dumps([i.get("ticket_url").encode("utf-8") for i in data])
ticket_statuses = json.dumps([i.get("ticket_status").encode("utf-8") for i in data])
venues = json.dumps([i["venue"] for i in data])
context = {
"form" : form,
"form_artistSelect" : form_artistSelect,
"raw_dts" : raw_dts,
"ticket_urls" : ticket_urls,
"ticket_statuses" : ticket_statuses,
"venues" : venues,
}
else:
context = {
"form" : form
}
return render(request,"searchform.html" , context)
So specifically, I have a couple of questions
As this view is the only one I have for the page, should I add other view functions for each button click event? Also, would be the proper way to send data for each concert list item to python on the server side where it can be saved for each user?
I would add two views
invite_concert
save_concert
At each click, you use the correct URL for that view, the view can return an empty HttpResponse, if you don't need any answer back.
For the parameters, I like sometimes to add the parameters I need to the HTML of the item, something like
data-concert-id=venues[i].id
But maybe you already have all the required data in your list item. Anyway, you can then retrieve them and use them easily in the data object of your ajax call, like:
{concert-id : $(this).attr('data-concert-id')

Categories