I have a problem with "like" functionality. I want to make it possible to like the post, without overloading the whole page. So I used CBV django connected to ajax.
My problem is that it receives: Not Found: /like/ by pressing the "Like" button.
My view:
class PostLikeView(generic.View):
def post(self, request):
post = get_object_or_404(Post, id=request.POST.get('id'))
is_liked = False
if post.likes.filter(id=request.user.id).exists():
post.likes.remove(request.user)
is_liked = False
else:
post.likes.add(request.user)
is_liked = True
context = {
'post': post,
'is_liked': is_liked,
'total_likes': post.total_likes(),
}
if request.is_ajax():
html = render_to_string('post/like_section.html', context, request=request)
return JsonResponse({'form': html})
Below is jquery code:
<script type="text/javascript">
$(document).ready(function(event){
$(document).on('click', '#like', function(event){
event.preventDefault;
var pk = $(this).attr('value');
$.ajax({
type: 'POST',
url: "{% url 'post:post_like' %}",
data: {'id': pk, 'csrfmiddlewaretoken': '{{ csrf_token }}'},
dataType: 'json',
success: function(response){
$('#like-section').html(response['form'])
console.log($('#like-section').html(response['form']))
},
error: function(rs, e){
console.log(rs.responseText);
},
});
});
});
</script>
url to view:
url(r'^like/$', login_required(PostLikeView.as_view()), name='post_like'),
code in html:
<form action="{% url 'post:post_like' %}" method="post">
{% csrf_token %}
{% if is_liked %}
<button type="submit" id="like" name="post_id" value="{{ post.id }}" class="btn btn-danger">Dislike</button>
{% else %}
<button type="submit" id="like" name="post_id" value="{{ post.id }}" class="btn btn-primary">Like</button>
{% endif %}
</form>
I would like the button to work on the principle of not reloading the whole page.
The issue I think is that you've not actually called event.preventDefault in your click event handler (you're missing the brackets). That means that the submit button submits the form, but the form doesn't contain a parameter named id and so get_object_or_404(Post, id=request.POST.get('id')) raises a 404.
Add the missing brackets to event.preventDefault, and also note that the value of id= attributes on HTML elements should be unique within the page. Change the values of the id= attributes on the <button> elements so that they are unique.
Related
So here is my issue.
The user can create a Client using a form.
Once created, the created client appears in a DetaiLView
In this DetailView, I put a form to add specific events related to the client, thanks to an ajaxified form so that new events appear without refreshing the page. So far everything is okay.
Now I would like to allow the user to delete one event if he wants to.
So I have done the HTML/AJAX parts. However, since it is a DetaiLView, I am having troubles to delete a specific event.
Here is my Views.py :
class CollectionDetail(LoginRequiredMixin, FormMixin, DetailView):
model = Collection
form_class = ImportantFactsForm
template_name = 'taskflow/collection_detail.html'
success_url = None
def get_context_data(self, **kwargs):
context = super(CollectionDetail, self).get_context_data(**kwargs)
context['important_facts'] = ImportantFactsForm()
return context
def post(self, request, *args, **kwargs):
form = ImportantFactsForm(request.POST)
tgt = self.get_object()
if form.is_valid():
new_fact = form.save(commit=False)
new_fact.collection_important_facts = tgt
new_fact.save()
return JsonResponse({'new_fact': model_to_dict(new_fact)}, status=200)
else:
return redirect('taskflow:collection_all')
#here I need to implement the delete function.
Here is my collection_detail.html
<div class="card-body">
<div class="tab-content">
<div class="tab-pane active" id="Canal1">
<form class="justify-content-center mx-3" id="createFactForm" method="post" data-url="{% url 'taskflow:collection_detail' pk=object.pk %}">
{% csrf_token %}
<div class="form-group">
{{important_facts.doc_ref|as_crispy_field}}
</div>
<div class="form-group">
{{important_facts.note|as_crispy_field}}
</div>
<button type="submit" class="btn btn-outline-success" id="createButton">Enregistrer</button>
</form>
{% if object.has_important_facts %}
{% for fact in object.has_important_facts.all %}
<div class="card mb-1" id="factCard" data-id="{{fact.id}}" data-url="{% url 'taskflow:collection_detail' pk=object.pk %}">
<div class="card-body">
{{fact.note}}
<form method="post">
{% csrf_token %}
<button type="submit" formmethod="post" name="DeleteFactButton" id="DeleteButtonFact" class="btn btn-danger float-right" data-id="{{fact.id}}">Delete</button>
</form>
</div>
</div>
{% endfor %}
{% endif %}
</div>
Here is my facts.js file
var csrfToken = $("input[name=csrfmiddlewaretoken]").val();
$(document).ready(function(){
$("#createFactForm").on('submit', function(evt) {
evt.preventDefault();
var CreateFactForm = $("#createFactForm");
$.ajax({
url: CreateFactForm.data('url'),
data: CreateFactForm.serialize(),
method: 'POST',
success: function(response) {
console.log(response)
$("#Canal1").append(
'<div class="card mb-1" id="taskCard" data-id="' + response.new_fact.id + '">'+
' <div class="card-body">'+
response.new_fact.note+
' <button type="button" class="btn btn-danger float-right" name="DeleteFactButton" id="DeleteButtonFact" data-id="' + response.new_fact.id + '">'+
' Supprimer'+
' </button>'+
' </div>'+
'</div>');
}
})
$("#createFactForm")[0].reset();
});
$("#DeleteButtonFact").on('click', function(response) {
console.log(response)
var dataID = $(this).data('id');
$.ajax({
url: $("#DeleteButtonFact").data('url'),
data:{
csrfmiddlewaretoken: csrfToken,
id: dataID
},
method: 'POST',
dataType: 'json',
success: function() {
$('#factCard[data-id="' + dataID + '"]').remove();
}
})
});
});
Thanks for your help !
You can use deleteView, add another url path and link it to class which inherits deleteView
also for you can check the response in ajax if an error occurred and do action accordingly
I am implementing Like functionality in Web application. Idea is Simple to List number of Post(Blogs) on Home page and Add a Like Button to each post(Blog). It works fine when I build it with normal
<form action='{% url target %}' method='POST'>
But when I implemented this with AJAX call It only allows me to like or dislike a particular post(blog) a single time.i.e One I liked a Post for first time it works, also when I dislike the same Post It works fine, But when I again Like that Post it throws an django.db.utils.OperationalError: database is locked
Also, when I like same post multiple(4 to 5) times it respond in a weird way. I goes in Loop of liking and dislikig post.
like_section.html
<form id="like-form{{ post.id }}">
{% csrf_token %}
<button type="submit" id="{{ post.id }}btn" name="like" value="{{ post.id }}" class="btn upvote">Like</button>
<script type="text/javascript">
{% for like in post.likes.all %}
{% if like != user %}
dislikingPost("{{ post.id }}btn");
{% else %}
likingPost("{{ post.id }}btn");
{% endif %}
{% endfor %}
$(document).ready(function(event){
$(document).on('click', '#{{ post.id }}btn', function(event){
event.preventDefault();
pk = $(this).attr('value');
$.ajax({
type: 'POST',
url: '{% url "like_post" %}',
data: {
'id': pk,
'csrfmiddlewaretoken': '{{ csrf_token }}'
},
success:function(response){
$('#like-form{{ post.id }}').html(response['form'])
// $('#{{ post.id }}btn').style.color = 'green';
}, error: function(er, e){
console.log(er.responseText);
}
});
});
});
</script>
</form>
views.py:
def like_post(request):
all_posts = Posts.objects.all()
print("Insisde Like Post")
print('ID coming from form is', request.POST.get('id'))
post = get_object_or_404(Posts, id=request.POST.get('id')) # for AJAX call
context = {
'all_posts': all_posts,
'post': post
}
if post.likes.filter(id=request.user.id).exists():
post.likes.remove(request.user) # Liking The Post
print("DisLiking the post")
else:
post.likes.add(request.user)
print("Liking the post")
if request.is_ajax():
print('Hey its an AJAX calls') # TEsting AJAX request
html = render_to_string('like_section.html', context, request=request)
return JsonResponse({'form': html})
Note:
1. I am beginner in AJAX.
2. I know SQLite can not handle redundant calls, But why it was working before without AJAX calls.
3. I am not providing models.py and complete template of home page and I don't think they are required.
The Problem was not with the Django code. It was ajax call which was triggering Database more then one time on a single Button Click.
Adding event.stopImmediatePropagation(); below event.preventDefault(); in ajax call works perfect
I want to create a comment system with using Ajax. My main purpose is getting new comments in my page without page refreshing. I add some js code to my HTML file but it didn't work. Where are my mistakes and what should I do?
views.py
...
def post_detail(request, pk, ):
post = get_object_or_404(Post, pk=pk)
form = CommentForm(request.POST or None)
if form.is_valid():
comment = form.save(commit=False)
comment.post = post
comment.save()
return redirect('post_detail', pk=post.pk)
context = {
'post': post,
'form': form,
}
return render(request, 'blog/post_detail.html', context)
comments.html
{% load crispy_forms_tags %}
{% load static %}
<hr>
<form method="POST" style="width: 50%; margin-left: 20px" id="comment_form">
{% csrf_token %}
{{ form|crispy }}
<input type="submit" class="btn btn-info" value="Yorum Ekle" style="margin-left: 20px">
</form>
<script type="text/javascript" src="{% static 'js/jquery-1.11.1.min.js' %}"></script>
<script type="text/javascript">
$(document).on('submit', '#comment_form', function (e) {
e.preventDefault();
$.ajax({
type: 'POST',
url: 'http://127.0.0.1:8000/post/12/',
data: {
name: $('#name').val(),
content: $('#content').val(),
created_date: $('#created_date').val(),
post: $('#post').val(),
csrfToken: $('input[name=csrfmiddlewaretoken]').val()
},
success: function () {
alert("YEAH! It works!");
}
}
)
})
</script>
post_detail.html
...
{% include 'blog/comment.html' %}
<hr>
{% for comment in post.comments.all %}
<h4>{{ comment.name }} | <small>{{ comment.created_date|timesince }} önce</small></h4>
<p>{{ comment.content|linebreaks }}</p>
{% endfor %}
urls.py
...
url(r'^post/(?P<pk>\d+)/$', views.post_detail, name='post_detail'),
When I click comment button there is no action. But when I look inspect elements, when I click button it shows Status code:403
Note: I get "YEAH! It works!" alert
You need to return a JsonResponse or a partial template in post_detail method so that you can use these data in ajax success function. I have created a django app for commenting system using ajax response for preventing page refresh. If you are interested Here the package repo
The success function takes an argument, which is the data sent back by the server.
Update your code like this:
success: function (result) {
alert("YEAH! It works!");
}
I'm allowing users to remove posts through ajax. Posts have a boolean field live_until_removed. When set to false, the post disappears.
When clicking remove I'm given a 403, referencing:
xhr.send( ( s.hasContent && s.data ) || null );
How do I get this to run smoothly? Why this this error happening?
js:
$('#removeForm').submit(function() { // catch the form's submit event
$.ajax({
data: $(this).serialize(),
type: $(this).attr('method'),
url: $(this).attr('action'),
success: function(response) {
$('.close-post').html(response); // update the DIV
console.log(response);
},
error: function(response){
console.log(response);
}
});
return false;
});
template:
<div class="close-post">
{% if not post.live_until_removed %}
<form class="" id="removeForm" method="POST" action="">
<button type="submit" class="btn">Remove</button>
</form>
{% else %}
<button class="btn">Removed</button>
{% endif %}
</div>
views.py:
def post(request, id):
...
if request.is_ajax():
try:
post = Post.objects.get(id=id)
post.live_until_removed = False
post.save()
response = simplejson.dumps({"status": "Removed"})
except:
pass
You might have missed to send CSRF token in your request. Look at here; Django-Ajax
I have a simple form to submit and test ajax,but it doesn't work and I see any problem in it,I searched alot and there was no more poin-at least I dedn't see ;)
in urls.py
(r'^doctors/shahsavand/visiting/$','DrHub.views.visiting'),
(r'^doctors/shahsavand/visiting/add/$','DrHub.views.ajxTest')
the first URL is to direct to main page and there's this form in main page:
<form method='POST' action=".">
{% csrf_token %}
<ul>
<li>
<label for="start">Start Time: </label><input name="id_startTime" id="id_startTime" type="text" />
</li>
<li>
<label for="end">End Time: </label><input name="id_endTime" id="id_endTime" type="text" />
</li>
</ul>
<input type="submit" id="save_button" name="save_button" value="add" />
</form>
and ajax code in this page:
<script type='text/javascript' src='/static/DrHub/doctors/shahsavand/js/jquery-1.4.1.js'></script>
<script type="text/javascript">
$.ajax({
type:"POST",
url:"{% url DrHub.views.ajxTest %}",
data: {
'start': $('#id_startTime').val(),
'end': $('#id_endTime').val(),
'csrfmiddlewaretoken':$( "#csrfmiddlewaretoken" ).val()
},
success: function(data){
alert(data);
}
});
</script>
in views.py :
def ajxTest(request):
if request.is_ajax():
if request.method == 'POST':
return HttpResponse(simplejson.dumps({'message' : 'awesome'}), mimetype='application/javascript')
else:
return render_to_response('DrHub/doctors/nutrition/test.html', context_instance=RequestContext(request))
I did this to test if ajxTest view is called:
def ajxTest(request):
if request.is_ajax():
raise Http404
else:
pass
and this :
def ajxTest(request):
if request.is_ajax():
raise pass
else:
Http404
but no result and that sounds like my ajax POST is not associated with ajxTest view !!!
edit
when I check firebug I get 403 forbidden error that is for CSRF and I've tryed many things to solve it again no result :(
Add the javascript described in the documentation for csrf and it should fix your problem.