Requesting Django server using ajax - javascript

my views.py -
def wall(request):
if request.method == 'POST':
post = request.POST
if 'logout' in post:
del request.session['username']
return redirect('home')
elif 'post' in post:
if post['post_text'] and not post['post_text'].isspace():
posted_by = request.session.get('username', '')
post_content = post['post_text']
post_id = posted_by+''+datetime.datetime.now().strftime("%I:%M%p on %B %d, %Y")
p = user_post(posted_by = posted_by, post_content = post_content, post_id = post_id)
p.save()
return redirect('wall')
else:
return redirect('error')
elif 'search_user' in post:
return redirect('search_user')
elif 'profile' in post:
return redirect('profile')
else:
if 'username' in request.session:
posts = user_post.objects.order_by('id')[:20].reverse()
return render(request, 'wall/wall_page.html', {'posts': posts, 'user': request.session['username']})
else:
return redirect('error')
template -
<div class="row" id="posts">
{% if posts %}
{% for post in posts %}
{% if user == post.posted_by %}
<p class="lead text-success text-right">
{{ post.post_content }}
<small>
<small>
<small>
<small>
{{ post.posted_by }}
</small>
</small>
</small>
</small>
</p>
{% else %}
<p class="lead text-info text-left">
{{ post.post_content }}
<small>
<small>
<small>
<small>
{{ post.posted_by }}
</small>
</small>
</small>
</small>
</p>
{% endif %}
{% endfor %}
{% endif %}
</div>
and related js file -
$(document).ready(function()
{
setInterval(function()
{
$.ajax(
{
type : "GET",
url : "http://10.8.21.17:8000/wall/wall",
}).done(function()
{
$('#posts').html();
});
}, 3000);
});
There is proper GET request to the server but the page is not reloading...i.e. when a user post something it is actually not showing to other users even if there is a GET request every 3 second. I copy-pasted the js code and dont know if it is correct. Anyone help me please. What i want to do is that the page should reload with the help of js so that user dont have to refresh.
Thanks in advance.

You're not doing anything with the response from the server in your JS. You need to actually use it:
.done(function(data)
{
$('#posts').html(data);
});

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 do disable redirecting when I clicking on a button? Django

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}`
}
})

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!

value gets submitted through form, then even after the value got submitted and gets displayed, in a form the value got submitted is shown

Sorry for the long title, but this is what happens:
I submit word "hello", then hello gets displayed. Then in a form, it still says "hello". I'm not sure why this is happening. Is this django problem or some javascript code is needed for this...?Here's my full code I think is causing this problem.
in my views.py
def post(request, slug):
user = get_object_or_404(User,username__iexact=request.user)
try:
profile = MyProfile.objects.get(user_id=request.user.id)
# if it's a OneToOne field, you can do:
# profile = request.user.myprofile
except MyProfile.DoesNotExist:
profile = None
post = get_object_or_404(Post, slug=slug)
post.views += 1 # increment the number of views
post.save() # and save it
path = request.get_full_path()
comments = Comment.objects.filter(path=path)
#comments = post.comment_set.all()
comment_form = CommentForm(request.POST or None)
if comment_form.is_valid():
parent_id = request.POST.get('parent_id')
parent_comment = None
if parent_id is not None:
try:
parent_comment = Comment.objects.get(id=parent_id)
except:
parent_comment = None
comment_text = comment_form.cleaned_data['comment']
new_comment = Comment.objects.create_comment(
user=MyProfile.objects.get(user=request.user),
path=request.get_full_path(),
text=comment_text,
post = post,
parent = parent_comment)
for c in comments:
c.get_children()
context_dict = {
'post' :post,
'profile' :profile,
'comments' : comments,
'comment_form':comment_form
}
return render(request, 'main/post.html', context_dict)
and in my post.html I have
<table class='table'>
{% for comment in comments %}
<tr><td>{{ comment.get_comment }}
<br/><small>via {{ comment.user }} | {{ comment.timestamp|timesince }} ago </small>
{% if not comment.is_child %}
<ul>
{% for child in comment.get_children %}
<li>{{ child.get_comment }}
<small>via {{ child.user }}</small>
</li>
{% endfor %}
</ul>
<a href='#' class='reply_btn'>Reply</a>
<div class='reply_comment'>
<form method="POST" action=''>{% csrf_token %}
<input type='hidden' name='parent_id' value='{{ comment.id }}' />
{{ comment_form.as_p }}
<input type='submit' class='btn btn-default' value='Add reply'/>
</form>
</div>
{% endif %}
</td></tr>
{% endfor %}
</table>
</div>
<div class = "col-sm-3">
</div>
{% include 'footer.html' %}
<script>
{% block jquery %}
$('.reply_btn').click(function(e){
e.preventDefault();
$(this).next(".reply_comment").fadeToggle();
// $(".reply_comment").fadeToggle();
})
{% endblock %}
</script>
{% endblock %}
Can someone please direct me where I should look.....thank you
Before you check if a form is valid or not you assign the form to include the POST data so it will still include this when you return back to the form (in case it needs to show errors). The easiest fix would be to reassign the form after your valid logic is done.
comment_form = CommentForm(request.POST or None)
if comment_form.is_valid():
.. Valid logic ..
comment_form = CommentForm()

Categories