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
});
Related
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}`
}
})
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>
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!
So I have been trying to implement a way to post a project post that is able to upload multiple images at the same time.
Both of my forms are not getting validated even tho they are correct and complete.
I am not sure what am I doing wrong.
My codes are below:
views.py
class CreateProjectsView(View):
def get(self, request):
p_photos = P_Images.objects.all()
#project_form = ProjectsForm(initial=self.initial)
project_form = ProjectsForm()
context = {
'p_photos': p_photos,
'project_form': project_form,
}
return render(self.request, 'projects/forms.html', context)
def post(self, request):
project_form = ProjectsForm(request.POST, request.FILES)
multi_img_form = P_ImageForm(request.POST, request.FILES)
if project_form.is_valid() and multi_img_form.is_valid():
instance = project_form.save(commit=False)
instance.user = request.user
instance.save()
images = multi_img_form.save(commit=False)
images.save()
data = {
'is_valid': True,
'name': images.p_file.name,
'url': images.p_file.url
}
else:
data = {
'is_valid': False,
}
return JsonResponse(data)
forms.html
{% extends "projects/test.html" %}
{% block javascript %}
<form action="{% url 'create_post:create_projects' %}" method="POST" enctype="multipart/form-data">
{% csrf_token %}
{% for hidden in project_form.hidden_fields %}
{{ hidden }}
{% endfor %}
{% for field in project_form %}
{{ field.errors }}
{{ field }} <br />
{% endfor %}
<input type="submit" value="OK">
{% load static %}
{# JQUERY FILE UPLOAD SCRIPTS #}
<script src="{% static 'projects/js/jquery-file-upload/vendor/jquery.ui.widget.js' %}"></script>
<script src="{% static 'projects/js/jquery-file-upload/jquery.iframe-transport.js' %}"></script>
<script src="{% static 'projects/js/jquery-file-upload/jquery.fileupload.js' %}"></script>
{# PHOTOS PAGE SCRIPTS #}
<script src="{% static 'projects/js/basic-upload.js' %}"></script>
{# 1. BUTTON TO TRIGGER THE ACTION #}
<button type="button" class="btn btn-primary js-upload-photos">
<span class="glyphicon glyphicon-cloud-upload"></span> Upload photos
</button>
{# 2. FILE INPUT TO BE USED BY THE PLUG-IN #}
<input id="fileupload" type="file" name="p_file" multiple
style="display: none;"
data-url="{% url 'create_post:create_projects' %}"
data-form-data='{"csrfmiddlewaretoken": "{{ csrf_token }}"}'>
{# 3. TABLE TO DISPLAY THE UPLOADED PHOTOS #}
<table id="gallery" class="table table-bordered">
<thead>
<tr>
<th>Photo</th>
</tr>
</thead>
<tbody>
{% for p_photo in p_photos %}
<tr>
<td>{{ p_photo.file.name }}</td>
</tr>
{% endfor %}
</tbody>
</table>
<h1>hahahaha</h1>
</form>
{% endblock %}
basic-upload.js
$(function () {
/* 1. OPEN THE FILE EXPLORER WINDOW */
$(".js-upload-photos").click(function () {
$("#fileupload").click();
});
/* 2. INITIALIZE THE FILE UPLOAD COMPONENT */
$("#fileupload").fileupload({
dataType: 'json',
done: function (e, data) { /* 3. PROCESS THE RESPONSE FROM THE SERVER */
if (data.result.is_valid) {
$("#gallery tbody").prepend(
"<tr><td><a href='" + data.result.url + "'>" + data.result.name + "</a></td></tr>"
)
}
}
});
});
No errors are getting posted are shown on my terminal. Its just that nothing simply happens. Nothing is getting uploaded to my database.
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()