Django Endlesss pagination breaks buttons genereated by endlesss pagination - django

I have endless pagination working on my site for posts.
Each post has a like and dislike button which works using ajax.
The first set of posts have working buttons but all posts delivered with pagination don't have working buttons. When clicking the buttons they don't even run the ajax to send a query to my views.py file but the first set of posts have working ones.
urls.py
path("likepost/", user_views.like_post_view, name='like_post'),
path("dislikepost/", user_views.dislike_post_view, name='dislike_post'),
views.py file
sort = request.GET.get("sort")
if sort=="newest":
posts = Post.objects.filter(deleted=False).order_by('-date_posted')
sort_type = "newest"
if sort=="oldest":
posts = Post.objects.filter(deleted=False).order_by('date_posted')
sort_type = "oldest"
if sort=="top-alltime":
posts = Post.objects.filter(deleted=False).annotate(like_count=(Count('like_post')-Count("dislike_post"))).order_by('-like_count')
sort_type = "top-alltime"
if sort==None or sort=="top-today":
today = datetime.now().date()
today_start = datetime.combine(today, time())
posts = Post.objects.filter(deleted=False, date_posted__gte=today_start).annotate(like_count=(Count('like_post')-Count("dislike_post"))).order_by('-like_count')
sort_type = "top-today"
if sort=="top-week":
current_week = date.today().isocalendar()[1]
posts = Post.objects.filter(deleted=False, date_posted__week=current_week).annotate(like_count=(Count('like_post')-Count("dislike_post"))).order_by('-like_count')
sort_type = "top-week"
page = request.GET.get('page', 1)
paginator = Paginator(posts, 4)
trending_tags = Post.tags.most_common()[:5]
try:
posts_given = paginator.page(page)
except PageNotAnInteger:
posts_given = paginator.page(1)
except EmptyPage:
posts_given = paginator.page(paginator.num_pages)
context = {
"trending_tags": trending_tags,
"posts_given": posts_given,
"sort": sort_type
}
return render(request, "users/index.html", context)
#login_required
#require_GET
def like_post_view(request):
print("LIKE REQUESTED!!!!!!!!!!!!!")
if request.method == 'GET':
user = request.user
user = User.objects.get(username=user)
post_id = request.GET.get('post_id', None)
post = Post.objects.get(id=post_id)
if like_post.objects.filter(user=user, post=post).exists():
# user has already liked this post
# remove like/user
like_post.objects.filter(user=user, post=post).delete()
#return -1
return HttpResponse(-1)
else:
# add a new like for the post
like_post.objects.create(post=post, user=user)
if dislike_post.objects.filter(user=user, post=post).exists():
dislike_post.objects.filter(user=user, post=post).delete()
return HttpResponse(+2)
return HttpResponse(+1)
#login_required
#require_GET
def dislike_post_view(request):
print("DISLIKE REQUESTED!!!!!!!!!!!!!")
if request.method == 'GET':
user = request.user
user = User.objects.get(username=user)
post_id = request.GET.get('post_id', None)
post = Post.objects.get(id=post_id)
if dislike_post.objects.filter(user=user, post=post).exists():
# user has already disliked this post
# remove dislike/user
dislike_post.objects.filter(user=user, post=post).delete()
return HttpResponse(+1)
else:
# add a new dislike for the post
dislike_post.objects.create(post=post, user=user)
if like_post.objects.filter(user=user, post=post).exists():
like_post.objects.filter(user=user, post=post).delete()
return HttpResponse(-2)
return HttpResponse(-1)
template
{% load static %}
{% block content %}
<h1>Homepage</h1>
<div class="infinite-container" id="infinite-container" style="max-width:700px;width:100%;margin-left:auto;margin-right:auto;">
<form action="/action_page.php">
{% csrf_token %}
<div style="display:inline-block;">
<h5 style="margin-left:10px;">Sort by</h5>
<select name="sort" class="sort_by" id="sort_by" style="margin-left:10px;">
<option value="newest">Newest</option>
<option value="top-today" selected="selected">Top Today</option>
<option value="top-week">Top This Week</option>
<option value="top-alltime">Top All Time</option>
<option value="oldest">Oldest</option>
</select>
</div>
</form>
{% for post in posts_given %}
<div class="post infinite-item" style="background-color:#494a4d;border-radius: 8px; color: white;padding:10px;margin:10px;">
<h2>{{ post.title }}<h2>
<hr>
<img src="/uploads/{{ post.image }}" alt="{{ post.image }}" style="max-width:100%; max-height:500px;">
<hr>
<div class="row-post">
<div class="column-post-left">
<h4 style="text-align: left;">by {{ post.user.username }} | {{ post.date_posted | timesince }} ago {% if request.user.is_authenticated and post.user == request.user %} | edit{% else %} | report{% endif %}</h4>
<h5 style="word-wrap: break-word;word-break: break-word;">{% for tag in post.tags.all %} #{{ tag }}{% endfor %}</h5>
<h5>{{ post.comment_count }} comments</h5>
</div>
<div class="column-post-right">
<input src="{% static "memeplaza/rocket_white.png" %}" type="image" style="max-width:50px;max-height:50px;" class="like" name="{{ post.id }}" value="Like"/>
<p style="font-size:22px;" id="{{ post.id }}">{{ post.like_count }}</p>
<input src="{% static "memeplaza/flash_white.png" %}" style="max-width:50px;max-height:50px;" type="image" class="dislike" name="{{ post.id }}" value="Dislike" />
</div>
</div>
</div>
{% endfor %}
</div>
{% if posts_given.has_next %}
<a class="infinite-more-link" href="?sort={{ sort }}&page={{ posts_given.next_page_number }}"></a>
{% endif %}
<script>
var infinite = new Waypoint.Infinite({element: $('.infinite-container')[0]});
$('.sort_by').change(function(){
var sort_type = $('#sort_by :selected').val();
window.location = "/?sort="+sort_type;
})
$('.like').click(function(){
var id = $(this).attr('name');
console.log("Like button pressed!");
$.ajax({
type: "GET",
url: "{% url 'like_post' %}",
data: {'post_id': $(this).attr('name'), 'csrfmiddlewaretoken': '{{ csrf_token }}'},
dataType: "json",
success: function(response){
var score = $("#" + id).text();
score = score.split(" ")[0];
score = parseInt(score) + parseInt(response);
$("#" + id).text(score);
}
});
})
$('.dislike').click(function(){
var id = $(this).attr('name');
console.log("disLike button pressed!");
$.ajax({
type: "GET",
url: "{% url 'dislike_post' %}",
data: {'post_id': $(this).attr('name'), 'csrfmiddlewaretoken': '{{ csrf_token }}'},
dataType: "json",
success: function(response){
var score = $("#" + id).text();
score = score.split(" ")[0];
score = parseInt(score) + parseInt(response);
$("#" + id).text(score);
}
});
})
</script>
{% if sort is not empty %}
<script>
$(document).ready(function(){
$("#sort_by").val("{{ sort }}");
});
</script>
{% endif %}
{% endblock content %}```

You should use $('selector').on for binding events to elements that do not exist yet
$('#infinite-container').on('click', '.like', function() {
...
})
$('#infinite-container').on('click', '.dislike', function() {
...
})
Using $('.like').click will only bind the event handler to elements that currently exist on the page

Related

Not entering Else Statement from user.is_authenticated

In the castmascotvote view, everything is working when I'm authenticated, but not working otherwise. I have a print('entering not authenticated') right when it enters the else statement if the user isn't authenticated, but it never enters it, i'm boggled. I don't understand at all why it's not working. does anyone have any idea where I should start looking?
error message
The view didn't return an HttpResponse object. It returned None instead.
But I clearly have a HttpResponse object!
.html
<form class="mascotvoteform" action="{% url 'castmascotvote' mascot.id %}" id="{{mascot.id}}">
<div class="p-0"><h4>{{ mascot.name }} </h4> <p> by {{ mascot.author }} </p></div>
<div class="p-0"><img class="img-thumbnail" src="{{ mascot.image.url }}" style="width:250px;"></div>
<div class="row p-3">
{% if mascot.total_votes is 0 %}
<div class="col"><h5 id="mascotvotes{{mascot.id}}">0</h5></div>
<button class="col btn btn-primary" type="submit" id="castmascotvote{{mascot.id}}">Vote</button>
{% else %}
<div class="p-0 col"><h5 id="mascotvotes{{mascot.id}}">{{ mascot.total_votes }}</h5></div>
<button class="col btn btn-primary" type="submit" id="castmascotvote{{mascot.id}}">Vote</button>
{% endif %}
</div>
</form>
.script
$( document ).ready(function() {
$(".mascotvoteform").submit(function(e) {
{% if user.is_authenticated %}
e.preventDefault()
{% endif %}
let mascot_id = $(this).attr("id");
let url = $(this).attr('action');
$.ajax({
type: 'POST',
url: url,
data: {
'csrfmiddlewaretoken': $('input[name=csrfmiddlewaretoken]').val(),
'mascot_id': mascot_id,
},
success: function(response) {
console.log('success', response)
$(`#mascotvotes${mascot_id}`).text(`${response['total_votes']}`)
};
},
error: function(response) {
console.log('error', response)
}
});
})
.views
def castmascotvote(request, mascot_id):
mascot = PoopMascot.objects.get(id=mascot_id)
user = request.user
if request.method == 'POST':
if user.is_authenticated:
if user in mascot.votes.all():
mascot.votes.remove(user)
else:
mascot.votes.add(user)
total_votes = mascot.total_votes()
data = { "total_votes":total_votes }
return JsonResponse(data, safe=False)
else:
print('entering user not authenticated')
messages.error(request, 'Please sign in to vote Poop Hero!')
return render(HttpResponseRedirect(reverse('user_login')))
else:
pass

Why Is Ajax Creating a New Comment When I'm Trying To Edit An Existing One?

I am trying to do a Django Blog in Class Based Views. They're proving very difficult to me anyway. I feel like I'm pretty close...I suspect it's creating a new one because I'm combining DetailView and trying to include an UpdateView in my page. I'm overriding POST on the DetailView...and perhaps that's why when I try to do my Update of the comment the overriden Post on DetailView is overriding that action?
Here's my code....
HTML...
<!DOCTYPE html>
<form method='POST' class="comment-form">
{% csrf_token %}
<div class="spacer284">
{{ form.comment }}
</div>
<button class="button7" type="submit">Submit</button>
</form>
<div class="spacer285">
{% include 'suggestion_comments.html' %}
</div>
</div>
{% endblock %}
Note that I'm doing an include so that I can loop through the comments more easily...
Here's the include template...
{% if suggestion_comments %}
<h2>Comments</h2>
{% for comment in object.suggestion_comments.all %}
<div class="spacer291">
<p>{{ comment.author }} {{ comment.created_on }}</p>
<p class="spacer290">{{ comment.comment }}</p>
<div class="spacer289">
<div class="upvote-comment-count">{{ comment.total_comment_upvotes }}</div>
<div class="hide-delete">
<button type="button" class="button6" data-href="{% url 'Suggestions:suggestion_comment_like' comment.id %}">Like</button>
</div>
<div class="hide-delete">
<button type="button" class="button2" data-href="">Reply</button>
</div>
{% if comment.author == request.user %}
<button type="button" class="button4" id="{{ comment.id }}" pk="{{ object.pk }}" href="{% url 'Suggestions:suggestion_comment_edit' object.pk comment.id %}">Edit</button>
<div class="spacer159" id="hide_payment" style="display:none;">
<input name="comment" id="commentInput" value="{{ comment.comment }}" class="name"/>
<button class="button7">Submit</button>
</div>
<div class="hide-delete">
{% if user.userprofile.eDirector_queue_delete_confirm == "Yes" %}
<button type="button" class="button5" data-href="{% url 'Suggestions:suggestion_delete' comment.id %}">Delete</button>
{% else %}
<button type="button" class="button3" data-href="{% url 'Suggestions:suggestion_delete' comment.id %}">Delete</button>
{% endif %}
</div>
{% endif %}
</div>
</div>
{% endfor %}
{% else %}
<h2>No Comments Yet</h2>
{% endif %}
I'm attempting to use AJAX to do a replace...
$(document).on('submit', '.comment-form', function(e) {
e.preventDefault();
var $this = $(this);
$.ajax({
type: "POST",
url: $this.data("href"),
data: $this.serialize(),
dataType: "json",
csrfmiddlewaretoken: "{{ csrf_token }}",
beforeSend: function(xhr) {
xhr.setRequestHeader("X-CSRFToken", "{{ csrf_token }}");
},
success: function(response){
console.log("so far");
$('.spacer285').html(response['form']);
$(".comment-form")[0].reset();
$('.spacer288').empty('spacer288');
},
error: function (request, status, error) {
console.log(request.responseText);
showAjaxFormErrors(JSON.parse(request.responseText));
},
});
});
$(document).on('click', '.button7', function(e) {
e.preventDefault();
console.log("working123");
var $this = $(this);
var comment = $('#commentInput').val();
console.log(comment);
$.ajax({
type: "POST",
url: $this.data("href"),
data: { comment: comment},
csrfmiddlewaretoken: "{{ csrf_token }}",
beforeSend: function(xhr) {
xhr.setRequestHeader("X-CSRFToken", "{{ csrf_token }}");
},
success: function(data){
console.log(data);
$('.comment-form1').html(data);
},
});
});
My DetailView...
class SuggestionDetailView(LoginRequiredMixin,DetailView):
model = Suggestion
context_object_name = 'suggestion_detail'
template_name = 'suggestion_detail.html'
def get_context_data(self, **kwargs):
context = super(SuggestionDetailView, self).get_context_data(**kwargs)
attachments = SuggestionFiles.objects.filter(suggestion=self.object.pk).all()
form = SuggestionCommentForm()
suggestion_comments = SuggestionComment.objects.filter(suggestion_id=self.object.pk).order_by('-created_on').all()
context['attachments'] = attachments
context['form'] = form
context['suggestion_comments'] = suggestion_comments
return context
def post(self, request, *args, **kwargs):
form = SuggestionCommentForm(request.POST)
if form.is_valid():
new_comment = form.save(commit=False)
new_comment.author = request.user
new_comment.suggestion = self.get_object()
new_comment.save()
self.object = self.get_object()
context = self.get_context_data(object=self.object)
html = render_to_string('suggestion_comments.html', context, request=self.request)
return JsonResponse({'form': html})
else:
form_errors = form.errors.as_json()
response = HttpResponse(form_errors, status=400)
response['content_type'] = 'application/json'
return response
MyCommentUpdateView...
class SuggestionCommentUpdateView(LoginRequiredMixin, UpdateView):
model = SuggestionComment
fields = ["comment"]
def form_valid(self, form):
form.instance.suggestion_id = self.kwargs["pk"]
return super().form_valid(form)
And my URLs...
path("a7900f81-b66a-41ea-afc2-d7735e6d4824/suggestion_detail/<uuid:pk>/suggestion_comment_edit/<int:id>",views.SuggestionCommentUpdateView.as_view(), name='suggestion_comment_edit'),
path("a7900f81-b66a-41ea-afc2-d7735e6d4824/suggestion_detail/<uuid:pk>/",views.SuggestionDetailView.as_view(), name='suggestion_detail'),
This is all almost working....My issue is when I click on the edit button and attempt to edit the comment....it works...and updates the database...but it's adding a new updated comment instead of just editing the existing comment. Thanks in advance for any thoughts on what I might be doing wrong.

Django - changing object value and displaying it without reloading

I got this model:
class OrderItem(models.Model):
order = models.ForeignKey(Order, on_delete=models.CASCADE)
item = models.ForeignKey(Product, on_delete=models.CASCADE)
quantity = models.IntegerField()
and I'd like to make user able to change its quantity value without reloading page
tried to do it this way:
views:
def increaseQuantity(request):
if request.method == 'GET':
orderItem_id = request.GET['orderItem_id']
orderitem = OrderItem.objects.get(id=orderItem_id)
orderitem.quantity += 1
orderitem.save()
url
path('cart/increase/', increaseQuantity, name='increase'),
template:
{% for product in products %}
<div >Some button content</div>
{% endfor %}
#
#
#
$('.quantity-increase').click(function(){
var orderItemId;
orderItemId = $(this).attr("data-orderItemId");
$.ajax({
type: "GET",
url: "increase",
data:{
orderItem_id:orderItemId
},
})
})
Quantity is being increased correctly, but I need to reload page to see results. What should I add/change to be allowed to see them without reloading ?
view used to see results:
def cart(request):
data = cartData(request)
cartItems = data['cartItems']
order = data['order']
items = data['items']
context = {'items':items, 'order':order, 'cartItems':cartItems}
return render(request, 'store/cart.html', context)
template
{% for item in items %}
<div class="cart-row">
<div style="flex:2"><img class="row-image" src="{{ item.product.imageURL }}"></div>
<div style="flex:2">{{ item.product.name }}</div>
<div style="flex:1">${{ item.product.price|floatformat:2 }}</div>
<div style="flex:1">
<p class = "quantity">{{item.quantity}}</p>
<div class = "quantity">
<img data-product={{item.product.id}} data-action="add" class="chg-quantity update-cart" src="{% static 'images/arrow-up.png' %}">
<img data-product={{item.product.id}} data-action="remove" class="chg-quantity update-cart" src="{% static 'images/arrow-down.png' %}">
</div>
</div>
<div style="flex:1">${{ item.get_total }}</div>
</div>
{% endfor %}
POST method is more suitable for this request
view
from django.http import JsonResponse
def increaseQuantity(request):
if request.method == 'POST':
if request.POST.get("operation") == "increase":
orderitem = OrderItem.objects.get(id=request.POST.get('orderItem_id', None))
orderitem.quantity += 1
orderitem.save()
return JsonResponse({'count':orderitem.quantity)
return JsonResponse({'error':'error')
html
{% for product in products %}
<div >Some button content</div>
{% endfor %}
#
#
#
$('.quantity-increase').click(function(){
var orderItemId;
orderItemId = $(this).attr("data-orderItemId");
$.ajax({
type: "POST",
url: "increase",
data:{
orderItem_id:orderItemId,
csrfmiddlewaretoken: '{{ csrf_token }}',
'operation':'increase'
},
success: function(data) {
$('.count-of-item').html(data.count) // your results element to show current quantity
console.log(data.count)
},
})
})

django ajax like button with css classes

hello I have a post model which has a like(m2m) and user(forgeinkey) model field and Im trying to check if the request.user has liked the post and if they have, I should show them a red heart button else a blue heart should be shown, now since there are multiple posts and likes, Im looping through each like object to check if the request.user has liked it or not. Unfortunately for some reason, I couldn't implement a good logic and I see like button for every user. Some help would be appreciated.
Here's my model:
class post(models.Model):
user = models.ForeignKey(User,default='' , related_name='has_liked', on_delete=models.CASCADE)
caption = models.CharField(max_length=100)
image = models.FileField(upload_to='images/', null=True, blank=True)
video = models.FileField(upload_to='videos/', null=True, blank=True)
created = models.DateTimeField(auto_now_add=True)
like = models.ManyToManyField(User, null=True, blank=True, default='')
The View:
#login_required
def usersfeed(request):
users = User.objects.all()
posts = post.objects.filter(Q(user__in=request.user.profile.friend.all()) | Q(user=request.user)).order_by('-created')
comments = Comment.objects.all()
status_form = StatusForm(request.POST)
friend_requests = FriendRequest.objects.filter(to_user=request.user)
friends = request.user.profile.friend.all()
for i in posts:
likes = i.like.all()
print(likes)
for like in likes:
if like.username == request.user.username:
if request.user:
Hasliked = True
print('liked')
else:
Hasnotliked = True
print('not liked')
context = {
'Post':posts,
'User':users,
'form':PostForm(),
'Profile':profile,
'Form':CommentForm(),
'Comment':comments,
'Status':status_form,
'fr':friend_requests,
'friend':friends,
'Hasliked':Hasliked,
'Hasnotliked':Hasnotliked,
}
return render(request, 'social_media/feed.html', context=context)
The view for ajax like counter:
#login_required
def like_post(request):
Post = get_object_or_404(post, id=request.GET.get('post_id'))
cssClass = 'colorRed'
if Post.like.filter(id=request.user.id).exists():
Post.like.remove(request.user)
else:
Post.like.add(request.user)
count = Post.like.count()
users = Post.like.all()
user = []
for i in users:
user.append((i.username))
response = {
'count':count,
'users':user,
'cssClass':cssClass,
}
return JsonResponse(response)
The Html code:
{% for i in Post %}
<form action="{% url 'like_post' %}" class='like-submit' data-catid="{{ i.id }}" method="GET">
<div class="like">
{% if Hasliked == True %}
<button id="likeBtn{{ i.id }}" class="likeClassBtn colorRed">
<i class="fas fa-heart"></i>
</button>
{% endif %}
{% if Hasnotliked == True %}
<button id="likeBtn{{ i.id }}" class="likeClassBtn">
<i class="fas fa-heart"></i>
</button>
{% endif %}
<div class="show_likes">
<span id="likes_count{{ i.id }}">{{ i.total_likes }}</span>
<div class="username_liked">
<div id="user-likes{{ i.id }}" class="user-likes">
{% for p in i.like.all %}
{{ p.username }}
{% endfor %}
</div>
</div>
</div>
</div>
</form>
{% endfor %}
<script>
$(document).ready(function () {
$(".like-submit").submit(function (event) {
event.preventDefault()
const url = $(this).attr('action');
const catid = $(this).attr("data-catid");
$.ajax({
type: "GET",
url: url,
data: {
post_id: catid,
},
success: function (data) {
$('#likes_count' + catid).html(data.count)
if ($('#user-likes' + catid).html()){
$('#user-likes' + catid).html(data.users + ' ')
$('#likeBtn' + catid).toggleClass(data.cssClass)
}
}
});
});
});
</script>
you need to store the hasLiked/hasNotLiked in the post record for that user. The code above, implies that all posts are either liked or unliked. You also need to rethink the way you load your context- the current code is extremely inefficient. I would suggest to replace the Hasliked and Hasnotliked context entries with id arrays where each one will contains the ids of the posts that the current user liked/disliked. Then in the template do in check:
{% if i.id in Hasliked %}
<button id="likeBtn{{ i.id }}" class="likeClassBtn colorRed">
<i class="fas fa-heart"></i>
</button>
{% endif %}
{% if i.id in Hasnotliked %}
<button id="likeBtn{{ i.id }}" class="likeClassBtn">
<i class="fas fa-heart"></i>
</button>
{% endif %}
the hasliked, disliked can be loaded using your current setup:
friends = request.user.profile.friend.all()
for i in posts:
likes = i.like.all()
print(likes)
for like in likes:
if like.username == request.user.username:
if request.user:
Hasliked.append(i.id)
print('liked')
else:
Hasnotliked.append(i.id)
print('not liked')
This it would be extremely inefficient, the best way to si ur is to query the database directly, and simply returning the ids:
l_likedPosts = PostActions.objects.filter(user_id=l_currUser,
liked=True)
.values_list('post_id',flat=True)
Hasliked = list(l_likedPosts)
The code above assumes that you have a table PostActions that contains at least the user_id, the post_id and the liked/disliked status. This is generally what the manytomany field does for you, behind the scenes, but using it takes too much freedom in more complicated data models.

Post method in django using ajax

I have a form that I am trying to implement with Ajax, after inputing some content on the textbox, when I click on the sumbit button using my mouse, everything works fine (page didnt refresh, data posted on database, and new data displayed on the page). But when I try to submit data by pressing enter, the page is displaying only the serialized data from my form (nothing more, html file do not work)and it says in the console:
Resource interpreted as Document but transferred with MIME type application/json: "http://localhost:8000/try/".
current page looks exactly like this after pressing enter button(nothing more):
{"task": {"id": 52, "todo": "wws", "author": 1, "completed": false}}
these are the data that came from my form.
this is my views.py
class TodoList(View):
def get(self, request):
todo_list = ToDo.objects.filter(author_id=request.user.id)
form = AddTodo()
context = {
'todo_list': todo_list,
'form': form,
}
return render(request, 'trylangto/try.html', context)
def post(self, request):
form = AddTodo(request.POST)
if form.is_valid():
form.instance.author_id = request.user.id
new_form = form.save()
return JsonResponse({'task': model_to_dict(new_form)}, status=200)
else:
return redirect('trylang:todo-list')
return redirect('trylang:todo-list')
this is my main.js:
$(document).ready(function(){
$("#createbutton").click(function(){
var formdata = $("#addtodoform").serialize();
$.ajax({
url: $("#addtodoform").data('url'),
data: formdata,
type: 'post',
success: function(response){
$("#tasklist").append('<div class="card mb-1" ><div class="card-body">'+ response.task.todo +'<button type="button" class="close"><span aria-hidden="true">×</span></button></div></div>')
}
});
});
});
and here is my template:
{% extends 'base.html' %}
{% load crispy_forms_tags %}
{% block content %}
{% if user.is_authenticated %}
<div class="media content-section">
<form class="media-body pt-3" method="POST" id="addtodoform" data-url="{% url 'trylang:todo-list' %}">
{% csrf_token %}
<legend><h5>add new tasks</h5></legend>
<fieldset class="form-group ">
{{ form|crispy}}
</fieldset>
<button class="btn btn-outline-info float-right" type="button" id="createbutton">add</button>
</form>
</div>
{% endif %}
<div id="tasklist">
{% for task in todo_list %}
<div class="card mb-1" >
<div class="card-body">
{{task.todo}}
<button type="button" class="close">
<span aria-hidden="true">×</span>
</button>
</div>
</div>
{% endfor %}
</div>
{% endblock %}
UPDATE: I am including my models.py just in case
class ToDo(models.Model):
todo = models.CharField(max_length=500)
date_posted = models.DateTimeField(default=timezone.now, editable=False)
author = models.ForeignKey(User, on_delete=models.CASCADE, related_name='users')
completed = models.BooleanField(default=False)
this is what I get on the console when I use console.log(formdata):
csrfmiddlewaretoken=N91OUGSd6kBFkB1E2DMZuMW6qJD7cc3frPprwGMLTuupcg6PKYtt44jA4z5Lx6xX&todo=this%20is%20the%20content%20of%20my%20textbox
You don't need model_to_dict. So, try:
if form.is_valid():
form.instance.author_id = request.user.id
new_form = form.save()
return JsonResponse({'task': new_form}, status=200)
else:
return redirect('trylang:todo-list')
return redirect('trylang:todo-list')
EDIT
You are submitting the form not through ajax. When you click button it was submitting the form. So, e.preventDefault() should do the job.
$(document).ready(function(){
$("#createbutton").click(function(e){
e.preventDefault(); <--- You were missing this
var formdata = $("#addtodoform").serialize();
$.ajax({
url: $("#addtodoform").data('url'),
data: formdata,
type: 'post',
success: function(response){
$("#tasklist").append('<div class="card mb-1" ><div class="card-body">'+ response.task.todo +'<button type="button" class="close"><span aria-hidden="true">×</span></button></div></div>')
}
});
});
});