How do disable redirecting when I clicking on a button? Django - javascript

I am trying to create a like button for my page. thats okey its working but when I click the button page is refreshing. When I click on the like button, I want the counter showing the number of likes to increase. I try used Ajax but I failed. here are my codes..
Views:
def liked_post(request,pk):
post =get_object_or_404(UserPosts, id=request.POST.get("userposts_id"))
liked = False
if post.like_post.filter(id = request.user.id).exists():
post.like_post.remove(request.user)
liked = False
else:
post.like_post.add(request.user)
liked = True
return HttpResponseRedirect(reverse('detail', args=[str(pk)] ))
def detail_post(request,_detail):
postDetail = UserPosts.objects.get(pk = _detail)
liked = False
if postDetail.like_post.filter(id= request.user.id).exists():
liked = True
context= {
"detail":postDetail,
"liked":liked
}
return render(request,"DetailPost.html",context)
Javascript file:
$(document).ready(function () {
//like ajax call
$('.like-form').submit(function (e) {
e.preventDefault();
const userposts_id = $('.like-btn').val();
const token = $('input[name=csrfmiddlewaretoken]').val();
const url = $(this).attr('action')
$.ajax({
method: "POST",
url: url,
headers: { 'X-CSRFToken': token },
data: {
'userposts_id': userposts_id
}
})
})
})
Template:
<form class="btn-group mt-1 like-form" action="{% url 'like_post' detail.pk %}"
method="POST">
{% csrf_token %}
{% if request.user.is_authenticated %}
{% if detail.username_id == request.user.id %}
<button class="btn btn-primary btn-sm" disabled>Like</button>
{% else %}
{% if liked %}
<button class="btn btn-danger btn-sm " type="submit" name="userposts_id"
value="{{ detail.id }}">Unlike</button>
{% else %}
<button class="btn btn-primary btn-sm like-btn"
type="submit" name="userposts_id" value="{{ detail.id }}">Like</button>
{% endif %}
{% endif %}
{% else %}
<span class="px-2 pt-1">
Login to like
</span>
{% endif %}
<span class="bg-dark px-4 pt-1 like-count text-white"> {{total_post_likes}}</span>
</form>
Does anyone have an idea?

You are redirecting to detail page in your like_post view. Instead of redirecting return JsonResponse
def liked_post(request):
if request.is_ajax():
pk = request.POST.get('userposts_id')
post = get_object_or_404(UserPosts,id=pk)
if request.user in post.like_post.all():
liked = False
post.like_post.remove(request.user)
else:
liked = True
post.liked.add(request.user)
return JsonResponse({'liked': liked, 'count': post.like_post.count()})
return redirect('detail')
this will return a json with liked and count .
<span class="bg-dark px-4 pt-1 like-count text-white"> {{total_post_likes}}</span>
Get span to render likes from js
$.ajax({
type: "GET",
url: url,
success: function (response) {
console.log(response) //response will be what you send in jsonresponse in django view
$('.like-count').innerHtml =`${response.count}`
}
})

Related

When using Fetch the page reloads (when it shouldn't) and only shows the Json data instead of the page that should be displayed

I am trying to make a basic twitter style application for a class project. When the like button is clicked the text in the button should then change to say unlike and the like count should increase by one without reloading the page. The database information is updated. The page itself reloads to a white background and the only thing on the page is my json data "{"likeButton": "Unlike", "total_likes": 0}", instead of the page itself. Any help would be appreciated.
Edit: here is a screenshot of the result I am getting
webpage screenshot
views.py
#login_required
def likes(request, post_id):
try:
current_user = request.user
post = Post.objects.get(id = post_id)
likeCount = Post.objects.get(id = post.id)
total_likes = likeCount.like_count
likeButton = request.POST.get('buttonForLikes')
if likeButton == 'Like':
total_likes = total_likes + 1
post.like_count = total_likes
post.save()
post.like.add(current_user)
post.save()
else:
total_likes = total_likes - 1
post.like_count = total_likes
post.like.remove(current_user)
post.save()
return JsonResponse ({'likeButton': likeButton, 'total_likes': total_likes,}, status=200,)
except KeyError:
return HttpResponseBadRequest("Like Error")
urls.py
from django.urls import path
from . import views
app_name = "network"
urlpatterns = [
path("", views.index, name="index"),
path("login", views.login_view, name="login"),
path("logout", views.logout_view, name="logout"),
path("register", views.register, name="register"),
path("new-post", views.new_post, name="new-post"),
path("profile/<str:username>", views.profile, name="profile"),
path("follows/<str:username>", views.follows, name="follows"),
path("following", views.following, name="following"),
path("edit", views.edit, name="edit"),
path("likes/<int:post_id>", views.likes, name='likes')
]
HTML
{% extends "network/layout.html" %}
{% load static %}
{% block body %}
{% if user.is_authenticated %}
<div class="borderDiv">
<div class="newPostCard">
<form id = "new_post_form" name="newPost" action = "{% url 'network:new-post' %}" method ="POST">
{% csrf_token %}
<label id="test"><h2>New Post</h2></label><br>
<textarea id="newPostBox" name="newPost"></textarea></textarea><br><br>
<input type ="submit" id = "new_post_submit" class = "btn btn-primary">
</form>
</div>
</div>
{% endif %}
<div class="newPostCard">
{% for item in all_post %}
<div class="borderDiv">
<div class="newPostCard">
<h2>{{ item.user }}</h2>
<p id="user_post">{{ item.post }}</p>
</div>
<form id = "like_form" method ="POST" action = "{% url 'network:likes' item.id %}" >
{% if request.user in item.like.all %}
<div> <button claas="likes" id = 'likeButton' data-id= '{{ item.id }}' value="Unlike" name="buttonForLikes">
Unike</button>: <span id="numOfLikes">{{ item.like_count }}</span>
{% csrf_token %}
</div>
{% else %}
<div> <button class="likes" id = 'likeButton' data-id= '{{ item.id }}' value="Like" name="buttonForLikes">
Like</button>: <span id="numOfLikes">{{ item.like_count }}</span>
{% csrf_token %}
</div>
{% endif %}
</form>
<div>
{% if user.is_authenticated and request.user == item.user %}
<button class ="btn btn-primary" id="edit">Edit</button>
{% endif %}
<textarea id="editText" name="editBox" style="display: none;"></textarea>
<button class="btn btn-primary" id="editSaveButton" style="display: none;">Save</button>
</div>
<p><i>{{ item.timestamp }}</i></p>
</div>
</div>
{% endfor %}
<div id="page_num">
<span class="page_numbers">
{% if all_post.has_previous %}
« first
previous
{% endif %}
<span class="current_page">
Page {{ all_post.number }} of {{ all_post.paginator.num_pages }}.
</span>
{% if all_post.has_next %}
next
last »
{% endif %}
</span>
</div>
</div>
<script src="{% static 'network/edit.js' %}"></script>
<script src="{% static 'network/likes.js' %}"></script>
{% endblock %}
javascript
let likes = document.getElementById('likeButton');
likes.addEventListener("click", (e) =>{
e.preventDefault();
e.stopPropagation();
let likeCount = document.getElementById('numOfLikes');
fetch(`/likes/${likes.dataset.id}`, {
credentials: "include",
method: "PUT",
headers: {
"Accept": "application/json",
'Content-Type': 'application/json',
},
})
.then(response => response.text())
.then(result => {
if (result.likeButton === 'Like'){
likes.innerHTML = "Unlike";
likeCount.innerHTML = result.total_likes;
}
else{
likes.innerHTML = 'Like';
likeCount.innerHTML = result.total_likes;
}
})
return false;
});

How can I use Ajax to display if username is already taken in django?

I'm trying to implement some code that will search if a username already exists and then display an error if it does dynamically rather than having to refresh the entire page. I tried implementing some JS and Ajax, but since I'm totally new to JS, it's not working and I'm not sure why. What am I doing wrong?
reg.html
{% extends "dating_app/base.html" %}
{% load bootstrap4 %}
{% block content %}
{% block javascript %}
<script>
$("#id_username").change(function () {
var username = $(this).val();
$.ajax({
url: '/ajax/check_if_username_exists_view/',
data: {
'username': username
},
dataType: 'json',
success: function (data) {
if (data.is_taken) {
alert("A user with this username already exists.");
}
}
});
});
</script>
{% endblock %}
<br>
<h1 class="text-center" style="color:#f5387ae6">Register to fall in love today!</h1>
<form method="post" style="width:700px;margin:auto" action="{% url 'dating_app:register' %}" enctype="multipart/form-data" class= "form" >
<div class="is-valid">
{% bootstrap_form registration_form%}
</div>
{% csrf_token %}
{% for field in bootstrap_form %}
<p>
{{field.label_tag}}
{{field}}
{% if field.help_text %}
<small style="color:grey;">{{field.help_text}}</small>
{% endif %}
{% for error in field.errors %}
<p style="color: red;">{{error}}"</p>
{% endfor %}
</p>
{% endfor %}
<div class="form-check">
<input type="checkbox" id="accept-terms" class="form-check-input">
<label for="accept-terms" class="form-check-label">Accept Terms & Conditions</label>
</div>
<div>
<br>
<button type="submit">Register</button>
</div>
</form>
{% endblock content %}
views.py/
def check_if_username_exists_view(request):
username = request.GET.get('username', None)
data = {
'is_taken': User.objects.filter(username__iexact=username).exists()
}
return JsonResponse(data)
urls.py/
path('ajax/check_if_username_exists_view/', views.check_if_username_exists_view, name='check_if_username_exists_view'),
models.py/
Class ProfileManager(BaseUserManager):
def create_user(self, username, email,description,photo, password=None):
if not email:
raise ValueError("You must creat an email")
if not username:
raise ValueError("You must create a username!")
if not description:
raise ValueError("You must write a description")
if not photo:
raise ValueError("You must upload a photo")
user = self.model(
email=self.normalize_email(email),
username = username,
description= description,
photo= photo,
)
user.set_password(password)
user.save(using=self._db)
return user
def create_superuser(self, username, email,description,photo, password):
user = self.create_user(
email=self.normalize_email(email),
password=password,
username=username,
description=description,
photo=photo,
)
user.is_admin=True
user.is_staff=True
user.is_superuser=True
user.save(using=self._db)
return user
class Profile(AbstractBaseUser):
class Meta:
swappable = 'AUTH_USER_MODEL'
email = models.EmailField(verbose_name="email")
username = models.CharField(max_length=30, unique=True)
date_joined = models.DateTimeField(verbose_name='date joined', auto_now_add=True)
last_login = models.DateTimeField(verbose_name='last login', auto_now=True)
is_admin = models.BooleanField(default=False)
is_active = models.BooleanField(default=True)
is_staff = models.BooleanField(default=False)
is_superuser = models.BooleanField(default=False)
#what I added
description = models.TextField()
photo = models.ImageField(upload_to='profile_photo',blank=False, height_field=None, width_field=None, max_length=100)
matches = models.ManyToManyField(settings.AUTH_USER_MODEL, related_name='+', blank=True)
USERNAME_FIELD = 'username'
REQUIRED_FIELDS = ['description','photo','email']
objects = ProfileManager()
def __str__(self):
return self.username
def has_perm(self, perm, obj=None):
return self.is_admin
def has_module_perms(self,app_label):
return True
So, in my base.html, which registration.html is inheriting from, I had 2 lines at the bottom of that page that were javascript lines that were not allowing Ajax to work because they were overriding the code I had in my registration.html. Once I removed them they started working.
<script src="https://code.jquery.com/jquery-3.3.1.slim.min.js" integrity="sha384-q8i/X+965DzO0rT7abK41JStQIAqVgRVzpbzo5smXKp4YfRvH+8abtTE1Pi6jizo" crossorigin="anonymous"></script>
<script>window.jQuery || document.write('<script src="../../assets/js/vendor/jquery-slim.min.js"><\/script>')</script>

Displaying comments using Ajax

i am working on a project using Django. There are lists of users posts in homepage and each post has a comment form. I was able to implement comment properly on views, but the issue now is when I submit a comment it display empty string instead of the comment, the comment display in chrome console. How do i display comment on each post by user when a form is submitted. I attached an image to my questioin to clarify my question.
home.html
<div id="newfeeds-form">
{% include 'ajax_newfeeds_comments.html' %}
</div>
ajax_newfeeds_comments.html
<!-- New Feeds comment Text -->
{% for post in all_images %}
<div class="container newfeeds-comment" id="display-comment">
{% for comment in post.comments_set %}
<div class="row">
<div class="col-1 col-md-1 col-lg-1">
{% if comment.user.profile.profile_pic %}
<img src="{{ comment.user.profile.profile_pic.url }}" class="d-flex rounded-circle" alt="image" height="28" width="28">
{% endif %}
</div>
<div class="col-10 col-md-10 col-lg-10 p-2 ml-1" id="user-commentpost">
<span class="comment-post truncate">
<span class="name text-lowercase">{{ comment.user }}</span>
{{ comment.comment_post }}</span>
</div>
</div>
{% endfor %}
</div>
{% endfor %}
<span class="md-form">
<form enctype="multipart/form-data" class="feeds-form form-inline md-form form-sm" method="POST" action="{% url 'site:home' %}" id="newfeeds-form{{ post.id }}">
{% csrf_token %}
<input type="hidden" value={{post.id}} name="post_comment">
<img src="{{ request.user.profile.profile_pic.url }}" class="rounded-circle avatar-img" height="28" width="28">
<textarea name="comment_post" class="textinput textInput animated fadeIn" placeholder="Add a comment..." required="" id="id_comment_post{{ post.id }}" onkeyup=""></textarea>
<button type="submit" class="submit" id="submit1-{{post.id}}"><i class="fas fa-paper-plane"></i></button>
</form
</span>
Views:
def home_view(request):
#All posts in new feed
all_images = Post.objects.filter(
Q(poster_profile=request.user, active=True)|
Q(poster_profile__from_user__to_user=request.user, active=True)|
Q(poster_profile__to_user__from_user=request.user, active=True)|
Q(poster_profile__profile__friends__user=request.user, active=True)).distinct().exclude(
Q(hide_post=request.user, active=True)|
Q(poster_profile__profile__blocked_users__user=request.user, active=True))
#Comment form homepage
if request.method == 'POST':
post_id = request.POST.get("post_comment")
post_obj = Post.objects.get(pk=post_id)
form = CommentForm(request.POST)
if form.is_valid():
comment = form.save(commit=False)
comment.user = request.user
comment.commented_image = post_obj
comment.save()
# messages.info(request,'You submitted a comment')
#return redirect('/')
else:
form = CommentForm()
context = {
'form': form,
'all_images': all_images,
}
if request.is_ajax():
html = render_to_string('ajax_newfeeds_comments.html', context, request=request)
return JsonResponse({'form': html})
return render(request,'home.html', context)
Ajax:
<script type="text/javascript">
//HomeFeeds Comment
$(document).ready(function() {
$('.feeds-form').on('submit', onSubmitFeedsForm);
$('.feeds-form .textinput').on({
'keyup': onKeyUpTextInput,
'change': onKeyUpTextInput
});
function onKeyUpTextInput(event) {
var textInput = $(event.target);
textInput.parent().find('.submit').attr('disabled', textInput.val() == '');
}
function onSubmitFeedsForm(event) {
event.preventDefault();
console.log($(this).serialize());
var form = $(event.target);
var textInput = form.find('.textinput');
var hiddenField = form.find('input[name="post_comment"]');
$.ajax({
type: 'POST',
url: "{% url 'site:home' %}",
data: form.serialize(),
dataType: 'json',
beforeSend: function() {
form.find('.submit').attr('disabled', true);
},
success: function(response) {
$('#newfeeds-form' + hiddenField.val()).html(response.form);
textInput.val('');
var numberOfCommentsElement = $('#number-of-comments');
numberOfCommentsElement.text(parseInt(numberOfCommentsElement.text()) + 1);
},
error: function(rs, e) {
console.log(rs.resopnseText);
},
complete: function() {
textInput.trigger('change');
}
});
}
});
</script>
You don't need ajax actually, you can simply:
let value = $('myInput').val();
$('myCommentContainer').prepend(`
Format the comment as you want ${value}
`)
$('myInput').val('') // To empty the value
now call the ajax normally:
$({
type: 'POST',
url: "{% url 'site:home' %}",
data: form.serialize(),
dataType: 'json',
beforeSend: function() {
form.find('.submit').attr('disabled', true);
},
success: function(response) {}
})
Done, leave the success empty
appending it within the ajax success will make it slower anyway!

Using Ajax change state of a clicked button

I am building a page in a Django project which has multiple comments each of which can be liked/unliked with a button next to the text. So the page has multiple like/unlike buttons.
The buttons display fine when the page is loaded, and I can use Ajax to send data to Django and update my database which works fine, and I can return data back to the Ajax success function.
What I can't work out is - how can I update the status of the actual button which was clicked. I am able to update the status of all of the buttons together on the page as per the code below (pointless I know!), but can't see how I reference the clicked button. I've tried passing and then returning the button id which I can display in an alert, but not sure if this is what I should be using or where I go from here?
HTML Template
{% for comments in comments_page %}
<p>
<b>{{ comments.created_at }} ({{ comments.user_type }})</b>
{% if comments.comment_liked is False %}
<button class="comment btn btn-primary btn-xs"
id={{ forloop.counter0 }}
data-surveyid="{{ comments.id }}"
data-commentliked="True"
type="button">
<span class="glyphicon glyphicon-star-empty"></span>
</button>
{% else %}
<button class="comment btn btn-success btn-xs"
id={{ forloop.counter0 }}
data-surveyid="{{ comments.id }}"
data-commentliked="False"
type="button">
<span class="glyphicon glyphicon-star"></span>
</button>
{% endif %}
</p>
<p>{{ comments.comments }}</p>
<br>
{% endfor %}
Javascript / Ajax
{% block javascript %}
<script type="text/javascript">
$(function() {
$('.comment').click(function() {
var surveyid, commentliked, buttonid;
surveyid = $(this).attr('data-surveyid');
commentliked = $(this).attr('data-commentliked');
buttonid = $(this).attr('id');
$.ajax({
url: '/evaluations/validate_username/',
data: {
'surveyid': surveyid,
'commentliked': commentliked,
'buttonid': buttonid
},
dataType: 'json',
type: 'get',
success: function (data) {
alert(data.buttonid);
$(".comment").removeClass('comment btn btn-primary btn-xs').addClass('comment btn btn-success btn-xs');
}
});
});
});
</script>
{% endblock %}
Just target the clicked button in your success function:
{% block javascript %}
<script type="text/javascript">
$(function() {
$('.comment').click(function() {
// the button instance that was clicked
var clickedBtn = $(this);
var surveyid, commentliked, buttonid;
// also, you can use data-* to get the data attributes
// surveyid = clickedBtn.attr('data-surveyid');
// commentliked = clickedBtn.attr('data-commentliked');
surveyid = clickedBtn.data('surveyid');
commentliked = clickedBtn.data('commentliked');
buttonid = clickedBtn.attr('id');
$.ajax({
url: '/evaluations/validate_username/',
data: {
'surveyid': surveyid,
'commentliked': commentliked,
'buttonid': buttonid
},
dataType: 'json',
type: 'get',
success: function (data) {
alert(data.buttonid);
clickedBtn.removeClass('comment btn btn-primary btn-xs')
.addClass('comment btn btn-success btn-xs');
}
});
});
});
</script>
{% endblock %}

AJAX update list of object

Can someone help me and say whats wrong I did?
In my django project I have product_detail page which has comment part. I am tring to update comments list after successfully adding new comment with AJAX. Unfortunatly it updates all page. I am little bit comfused and need advice. I need to update only list of comments not all page.
product_detail.html:
<div class="card">
<div class="card-block">
<table id="comment-table">
<thead>
<tr>
<th>Author</th>
<th>Date</th>
<th>Comment Text</th>
</tr>
</thead>
<tbody>
{% include 'project/comment_list.html' %}
</tbody>
</table>
</div>
<div class="card-footer">
<form method="post" class="comment-form" id="comment-form" action="{% url 'project:comment_add' project_code=project.code product_code=product.code %}">
{% csrf_token %}
{% for field in form %}
<div class="form-group{% if field.errors %} has-error{% endif %}">
{% render_field field class="form-control" %}
{% for error in field.errors %}
<p class="help-block">{{ error }}</p>
{% endfor %}
</div>
{% endfor %}
<button type="submit" class="btn btn-primary">Send</button>
</form>
</div>
</div>
views.py:
def comment_add(request, project_code, product_code):
data = dict()
project = get_object_or_404(Project, pk=project_code, status='open')
product = get_object_or_404(Product, pk=product_code)
if request.method == 'POST':
form = CommentForm(request.POST)
if form.is_valid():
comment = form.save(commit=False)
comment.author = request.user
comment.save()
product.comments.add(comment)
data['form_is_valid'] = True
data['html_comment'] = render_to_string('project/comment_list.html', {'product': product})
form = CommentForm()
else:
data['form_is_valid'] = False
else:
form = CommentForm()
context = {'project': project, 'product': product, 'form': form}
return render(request, 'project/product_detail.html', context)
js:
$(function () {
var saveForm = function () {
var form = $(this);
$.ajax({
url: form.attr("action"),
data: form.serialize(),
type: form.attr("method"),
dataType: 'json',
success: function (data) {
if (data.form_is_valid) {
$("#comment-table tbody").html(data.html_comment);
}
else {
$("#comment-form").html(data.html_comment_form);
}
}
});
return false;
};
$("#comment-form").on("submit", ".comment-form", saveForm);
});
The problem is type="submit" native refresh new page. You have to stop form submitting. Try something like this:
$("#comment-form").submit(function(event) {
/* stop form from submitting normally */
event.preventDefault();
// here your ajax code
});

Categories