【发布时间】:2020-12-28 19:36:24
【问题描述】:
我正在尝试使用 ajax 在我的 Django 站点中创建一个支持系统,这样当用户单击支持按钮时它不会刷新。在我的站点的主页中,所有帖子的列表视图中,我都能够让 ajax 和 upvote 请求工作,但仅限于顶部帖子。无论我是否点击另一个帖子的投票按钮,它只会在顶部帖子上注册效果。我哪里做错了? 下面是我的代码。
models.py
User = settings.AUTH_USER_MODEL #this is the user model
class Post(models.Model):
user = models.ForeignKey(User, on_delete=models.CASCADE) #many to one relationship where many posts can be tied to one user
content = models.TextField(blank=True, null=True)
date_posted = models.DateTimeField(default=timezone.now)
image = models.ImageField(upload_to='trade_images', blank=True, null=True)
upvotes = models.ManyToManyField(User, blank=True, related_name='upvotes')
total_upvotes = models.IntegerField(default='0')
def get_absolute_url(self):
return reverse('main:post-detail', kwargs={'pk': self.pk}) #returns the url for individual posts
def __str__(self):
return self.content
class Upvote(models.Model):
user = models.ForeignKey(User, related_name='upvoted_user', on_delete=models.CASCADE)
post = models.ForeignKey(Post, related_name='upvoted_post', on_delete=models.CASCADE)
def __str__(self):
return str(self.user) + ':' + str(self.post)
views.py
# list of all posts
class post_list_view(ListView):
model = Post
template_name = 'main/home.html'
context_object_name = 'posts' # this is called from the html as 'for post in posts'
ordering = ['-date_posted'] # minus to reverse the date posted, so newer posts show up on top
paginate_by = 5 #sets pagination per page
return context
def upvote(request):
if request.POST.get('action') == 'post':
result = ''
id = int(request.POST.get('postid'))
post = get_object_or_404(Post, id=id) #grabbing the selected post using postid
new_relation = Upvote(user=request.user, post=post) #storing the upvote relation between user and post using Upvote model arguments - 'user' and 'post'
if post.upvotes.filter(id=request.user.id).exists(): #checking if user already has upvote relations with post by filtering user and post
post.upvotes.remove(request.user) #remove upvote relation from post
post.total_upvotes -= 1 #minus 1 total_upvotes from post
result = post.total_upvotes #storing the new total_upvotes into result
Upvote.objects.filter(user=request.user, post=post).delete() #filtering user and post and deleting the upvote table
post.save()
else:
post.upvotes.add(request.user)
post.total_upvotes += 1
result = post.total_upvotes
print('create upvote')
new_relation.save()
post.save()
return JsonResponse({'result': result }) # return the new total_vote count back to html as json
template.html
<div id="upvote-section" class="card-footer">
{% if user.is_authenticated %}
<form action="{% url 'main:upvote-post' %}" method=POST>
{% csrf_token %}
<button type="submit" class="btn btn-success btn-sm" id="upvote-btn" name="post_id" value="{{post.id}}">Upvote</button>
<button type="submit" class="btn btn-outline-success btn-sm" id="upvote-btn" name="post_id" value="{{post.id}}">Upvote</button>
<p id="total_upvotes">
{{ post.total_upvotes }}
</p>
<a href="{% url 'main:post-detail' post.id %}" class="card-link"></i> Comment</a>
{% if post.user == user %}
<a href="{% url 'main:post-update' post.id %}" class="card-link">Edit</a>
<a href="{% url 'main:post-delete' post.id %}" class="card-link" style="color:red">Delete</a>
{% endif %}
</form>
{% else %}
Upvotes ({{ post.total_upvotes }}) Please login to upvote or comment.
{% endif %}
</div>
脚本/ajax
<script>
$(document).on('click', '#upvote-btn', function (e) {
e.preventDefault();
$.ajax({
type: 'POST',
url: '{% url "main:upvote-post" %}',
data: {
postid: $('#upvote-btn').val(),
csrfmiddlewaretoken: $('input[name=csrfmiddlewaretoken]').val(),
action: 'post'
},
success: function (json) {
document.getElementById("total_upvotes").innerHTML = json['result']
},
error: function (xhr, errmsg, err) {
console.log(err)
}
});
})
</script>
【问题讨论】:
标签: python jquery django ajax django-views