Django点赞功能开发遇id字段类型错误求助
Django点赞功能异步提交报错:Field 'id' expected a number but got ''
问题描述
学习Python时跟着视频教程开发Django点赞功能,用JavaScript实现异步提交,但执行post_obj = Post.objects.get(id=post_id)时触发错误,提示“Field 'id' expected a number but got ''”(空字符串无法转为整数)。尝试将post_id = request.POST.get('post_id')改为post_id = request.POST.get('id'),问题依旧。
相关代码
models.py
class Post(models.Model): title = models.CharField(max_length=222, verbose_name='Заголовок') text = models.TextField(blank=True, verbose_name='Текст') user = models.ForeignKey(User, on_delete=models.SET_NULL, null=True) views = models.ManyToManyField(IpModel, related_name="post_views", blank=True) def total_views(self): return self.views.count() def publish(self): self.published_date = timezone.now() self.save() def __str__(self): return self.title def get_absolute_url(self): return reverse('new_detail', kwargs={'pk': self.pk}) LIKE_CHOICES = ( ('Like', 'Like'), ('Unlike', 'Unlike'), ) class Like(models.Model): user = models.ForeignKey(User, on_delete=models.SET_NULL, null=True) post = models.ForeignKey(Post, on_delete=models.CASCADE) value = models.CharField(choices=LIKE_CHOICES, max_length=8) updated = models.DateTimeField(auto_now=True) created = models.DateTimeField(auto_now_add=True) def __str__(self): return f"{self.user}-{self.post}-{self.value}"
views.py
def like_unlike_post(request): user = request.user if request.method == 'POST': post_id = request.POST.get('post_id') post_obj = Post.objects.get(id=post_id) user = Post.objects.get(user=user) if user in post_obj.liked.all(): post_obj.liked.remove(user) else: post_obj.liked.add(user) like, created = Like.objects.get_or_create(user=user, post_id=post_id) if not created: if like.value=='Like': like.value='Unlike' else: like.value='Like' else: like.value='Like' post_obj.save() like.save() return redirect('like_button:main-post-view')
urls.py
urlpatterns = [ path('', index, name='index'), path('liked/', like_unlike_post, name='like-post-view'), ]
HTML及JS代码
<div class="content"> <p> {{ obj.content }} </p> <div class="right floated"> <form action="{% url 'like_button:like-post-view' %}" method="POST" class='like-form' id='{{obj.id}}'> {% csrf_token %} <input type="hidden" name="post_id" value={{obj.id}}> <button type="submit" class="ui button like-btn{{obj.id}}"> ❤ {% if profile not in obj.liked.all %} Like {% else %} Unlike {% endif %} </button> <div class="ui grid"> <div class="column"> <div class="like-count{{obj.id}}"> {{obj.num_likes}} </div> </div> <div class="column"> likes </div> </div> </form> </div> <script> $( document ).ready(function() { let display = false $(" .cmt_btn").click(function () { if (display===false) { $(this).next(".comment-box").show("slow"); display=true } else { $(this).next(".comment-box").hide("slow"); display=false } }); $('.like-form').submit(function(e){ e.preventDefault() const post_id = $(this).attr('id') const likeText = $(`.like-btn${post_id}`).text() const trim = $.trim(likeText) const url = $(this).attr('action') let res; const likes = $(`.like-count${post_id}`).text() const trimCount = parseInt(likes) $.ajax({ type: 'POST', url: url, data: { 'csrfmiddlewaretoken': $('input[name=csrfmiddlewaretoken]').val(), 'post_id':post_id, }, success: function(response) { if(trim === 'Unlike') { $(`.like-btn${post_id}`).text('Like') res = trimCount - 1 } else { $(`.like-btn${post_id}`).text('Unlike') res = trimCount + 1 } $(`.like-count${post_id}`).text(res) }, error: function(response) { console.log('error', response) } }) }) }); </script>
问题根源及解决方案
1. 核心错误原因
- JS通过
$(this).attr('id')获取表单id作为post_id,若模板中{{obj.id}}渲染失败(如obj无效、变量名错误),会拿到空字符串。 - views.py存在致命逻辑错误:
user = Post.objects.get(user=user)将用户对象覆盖为Post对象,后续逻辑全错;且Post模型未定义liked字段,post_obj.liked.all()本身就会报错。
2. 分步修复
修复views.py(关键)
from django.http import JsonResponse from django.contrib.auth.decorators import login_required @login_required def like_unlike_post(request): if request.method == 'POST': post_id = request.POST.get('post_id') # 校验post_id有效性 if not post_id: return JsonResponse({'status': 'error', 'message': '缺少文章ID'}, status=400) try: post_id = int(post_id) except ValueError: return JsonResponse({'status': 'error', 'message': '无效的文章ID'}, status=400) try: post_obj = Post.objects.get(id=post_id) except Post.DoesNotExist: return JsonResponse({'status': 'error', 'message': '文章不存在'}, status=404) # 通过Like模型判断是否已点赞 liked = Like.objects.filter(user=request.user, post=post_obj, value='Like').exists() if liked: # 取消点赞 Like.objects.filter(user=request.user, post=post_obj).update(value='Unlike') else: # 添加点赞 Like.objects.update_or_create(user=request.user, post=post_obj, defaults={'value': 'Like'}) # 计算最新点赞数 num_likes = Like.objects.filter(post=post_obj, value='Like').count() # 返回JSON给前端,AJAX请求不要redirect return JsonResponse({'status': 'success', 'num_likes': num_likes, 'liked': not liked}) return JsonResponse({'status': 'error', 'message': '仅支持POST请求'}, status=400)
修复Post模型,添加点赞数方法
在Post类中新增方法,方便模板调用:
class Post(models.Model): # 原有字段... def num_likes(self): return Like.objects.filter(post=self, value='Like').count()
修复HTML模板
- 修正变量错误:
{{ obj.content }}改为{{ obj.text }}(Post模型字段是text) - 调整选择器,从隐藏input获取post_id更可靠:
<div class="content"> <p> {{ obj.text }} </p> <div class="right floated"> <form action="{% url 'like_button:like-post-view' %}" method="POST" class='like-form'> {% csrf_token %} <input type="hidden" name="post_id" value="{{ obj.id }}"> <button type="submit" class="ui button like-btn"> ❤ {% if request.user.is_authenticated and Like.objects.filter(user=request.user, post=obj, value='Like').exists %} Unlike {% else %} Like {% endif %} </button> <div class="ui grid"> <div class="column"> <div class="like-count"> {{ obj.num_likes }} </div> </div> <div class="column"> likes </div> </div> </form> </div>
修复JS代码
- 从隐藏input获取post_id,避免依赖表单id
- 处理后端返回的JSON数据,提升健壮性:
$( document ).ready(function() { let display = false $(" .cmt_btn").click(function () { if (display===false) { $(this).next(".comment-box").show("slow"); display=true } else { $(this).next(".comment-box").hide("slow"); display=false } }); $('.like-form').submit(function(e){ e.preventDefault() const $form = $(this) const post_id = $form.find('input[name="post_id"]').val() const $likeBtn = $form.find('.like-btn') const $likeCount = $form.find('.like-count') $.ajax({ type: 'POST', url: $form.attr('action'), data: $form.serialize(), dataType: 'json', success: function(response) { if(response.status === 'success') { $likeCount.text(response.num_likes) $likeBtn.text(response.liked ? 'Unlike' : 'Like') } else { alert(response.message) } }, error: function(xhr) { const res = xhr.responseJSON || {} alert(res.message || '点赞失败,请重试') } }) }) });
修复urls.py(确保命名空间正确)
添加app_name,避免URL反向解析冲突:
app_name = 'like_button' urlpatterns = [ path('', index, name='index'), path('liked/', like_unlike_post, name='like-post-view'), ]
内容的提问来源于stack exchange,提问作者Alia
相关产品推荐
相关产品推荐

