Flask项目中取消点赞后仍显示已点赞的问题修复求助
Flask点赞功能异常修复:取消点赞后状态不更新
问题现象
用户取消点赞后,点赞按钮颜色仍显示为已点赞状态,点赞数也未减少。各状态表现:
- 未点赞时:

- 已点赞时:

- 取消点赞后异常状态:

问题代码分析
后端路由代码
@app.route('/postlikes/<string:post_name>', methods=["GET","POST"]) def postlikes(post_name): if request.method == "POST": JSONdata = request.json posts = Image.query.filter_by(post_name=post_name) if JSONdata['is_liked'] == True: for post in posts: post.likes += 1 db.session.commit() elif JSONdata['removed_like'] == True: for post in posts: post.likes = post.likes # 错误:未减少点赞数 db.session.commit() else: post = Image.query.filter_by(post_name=post_name).first() return {"post_likes":post.likes} @app.route('/hasliked/<string:post_name>', methods=['GET','POST']) def hasliked(post_name): post = Image.query.filter_by(post_name=post_name).first() user = User.query.filter_by(username=current_user.username).first() is_liked = posts_liked_by_users.query.filter_by(post_name=post_name).first() if is_liked.post_name == post.post_name and is_liked.user_id == user.id: # 错误:无数据时会抛异常 return {"has_liked":True} else: return {"has_liked":False}
前端JS代码
<script> const likebtn = document.getElementById('likebtn'); const currentURL = window.location.href; const likenum = document.getElementById('likenumber'); const postarray = currentURL.split("/"); const postName = postarray[4]; function setLikeBtnColor() { likebtn.style.color = JSON.parse(localStorage.getItem('likebtn')) ? 'cornflowerblue':'black'; } setLikeBtnColor(); async function current_color() { const fetchData = await fetch('/hasliked/'+postName) .then(response => response.json()) .then(function newdata(data) { let strdata = JSON.stringify(data) let JSONdata = JSON.parse(strdata) // 冗余:无需重复序列化反序列化 return JSONdata }) return fetchData } async function set_color() { const jsondata = await current_color() if (jsondata['has_liked'] === true) { likebtn.style.color = 'cornflowerblue' } else { likebtn.style.color = 'black' } } async function getLikeNumber() { const fetchData = await fetch('/postlikes/'+postName) .then(response => response.json()) .then(function getdata(data) { let strdata = JSON.stringify(data) let JSONdata = JSON.parse(strdata) // 冗余:无需重复序列化反序列化 likenum.textContent = JSONdata.post_likes return JSONdata.post_likes }) return fetchData } async function displayLikes() { let initialnum = await getLikeNumber() likenum.innerHTML = initialnum } displayLikes() async function myFunction() { localStorage.setItem('likebtn', !JSON.parse(localStorage.getItem('likebtn'))); setLikeBtnColor(); // 错误:先改UI再发请求,请求失败会导致状态不一致 if (likebtn.style.color === 'cornflowerblue') { fetch('/postlikes/'+postName, { method:"POST", body: JSON.stringify({ removed_like: false, liked_post:postName, is_liked:true }), headers:{ "Content-type":"application/json; charset=UTF-8" } }) let currentLikeNum = await getLikeNumber(); likenum.innerHTML = currentLikeNum } else { fetch('/postlikes/'+postName, { method:"POST", body: JSON.stringify({ removed_like:true, is_liked:false }), headers:{ "Content-type":"application/json; charset=UTF-8" } }) let currentLikeNum = await getLikeNumber(); likenum.innerHTML = currentLikeNum }}; likebtn.addEventListener('click', myFunction); </script>
Image数据表定义
class Image(db.Model): id = db.Column(db.Integer, primary_key=True) title=db.Column(db.String(120), nullable=False) date_posted = db.Column(db.DateTime, nullable=False, default=datetime.datetime.utcnow) img_location = db.Column(db.String(600), nullable=False) mimetype = db.Column(db.String(10)) post_name = db.Column(db.String(150),nullable=False, unique=False) user_id = db.Column(db.Integer, db.ForeignKey('user.id'), nullable=False) manga_name = db.Column(db.String(100), unique=False, nullable=False) likes = db.Column(db.Integer, nullable=False) reports = db.Column(db.Integer, nullable=False) number_of_comments = db.Column(db.Integer, nullable=False)
修复方案
1. 修复后端点赞计数与状态判断逻辑
修改postlikes路由中取消点赞的代码,同时完善hasliked路由的查询逻辑,避免无数据时抛异常,还要同步维护用户点赞关系表:
@app.route('/postlikes/<string:post_name>', methods=["GET","POST"]) def postlikes(post_name): if request.method == "POST": JSONdata = request.json posts = Image.query.filter_by(post_name=post_name) user = current_user if not user.is_authenticated: return {"status": "error", "msg": "未登录"} if JSONdata.get('is_liked'): # 增加点赞数 for post in posts: post.likes += 1 # 同步记录用户点赞关系 existing_like = posts_liked_by_users.query.filter_by( post_name=post_name, user_id=user.id ).first() if not existing_like: new_like = posts_liked_by_users(post_name=post_name, user_id=user.id) db.session.add(new_like) db.session.commit() elif JSONdata.get('removed_like'): # 减少点赞数(避免负数) for post in posts: if post.likes > 0: post.likes -= 1 # 删除用户点赞关系 existing_like = posts_liked_by_users.query.filter_by( post_name=post_name, user_id=user.id ).first() if existing_like: db.session.delete(existing_like) db.session.commit() else: post = Image.query.filter_by(post_name=post_name).first() return {"post_likes": post.likes if post else 0} @app.route('/hasliked/<string:post_name>', methods=['GET','POST']) def hasliked(post_name): if not current_user.is_authenticated: return {"has_liked": False} # 同时按post_name和用户ID查询,准确判断当前用户是否点赞 is_liked = posts_liked_by_users.query.filter_by( post_name=post_name, user_id=current_user.id ).first() return {"has_liked": is_liked is not None}
2. 修复前端状态同步逻辑
去掉冗余的JSON序列化操作,优先依赖后端状态更新UI,避免先改UI再发请求导致的不一致:
<script> const likebtn = document.getElementById('likebtn'); const currentURL = window.location.href; const likenum = document.getElementById('likenumber'); const postarray = currentURL.split("/"); const postName = postarray[4]; // 从后端获取并设置按钮状态 async function setLikeBtnState() { try { const response = await fetch('/hasliked/' + postName); const data = await response.json(); likebtn.style.color = data.has_liked ? 'cornflowerblue' : 'black'; // 可选:用localStorage缓存状态,用于离线场景 localStorage.setItem(`likebtn_${postName}`, data.has_liked); } catch (err) { console.error('获取点赞状态失败:', err); // 离线时用localStorage缓存的状态 const cachedState = JSON.parse(localStorage.getItem(`likebtn_${postName}`)) || false; likebtn.style.color = cachedState ? 'cornflowerblue' : 'black'; } } // 获取并更新点赞数 async function updateLikeNumber() { try { const response = await fetch('/postlikes/' + postName); const data = await response.json(); likenum.textContent = data.post_likes; } catch (err) { console.error('获取点赞数失败:', err); } } // 初始化页面状态 async function initPageState() { await Promise.all([setLikeBtnState(), updateLikeNumber()]); } initPageState(); // 处理点赞按钮点击事件 async function handleLikeClick() { try { // 先获取当前后端状态 const stateRes = await fetch('/hasliked/' + postName); const currentState = await stateRes.json(); const newState = !currentState.has_liked; // 发送修改请求 await fetch('/postlikes/' + postName, { method: "POST", body: JSON.stringify({ is_liked: newState, removed_like: !newState }), headers: { "Content-type": "application/json; charset=UTF-8" } }); // 请求成功后更新UI和缓存 likebtn.style.color = newState ? 'cornflowerblue' : 'black'; localStorage.setItem(`likebtn_${postName}`, newState); await updateLikeNumber(); } catch (err) { console.error('点赞操作失败:', err); // 请求失败时刷新状态,回滚UI await initPageState(); } } likebtn.addEventListener('click', handleLikeClick); </script>
3. 关键注意点
- 必须确保
posts_liked_by_users表在点赞/取消点赞时同步新增/删除记录,否则hasliked接口无法正确判断用户点赞状态 - 增加用户登录校验,避免未登录用户操作点赞
- 点赞数修改时增加边界判断,防止出现负数
内容的提问来源于stack exchange,提问作者user19552868
相关产品推荐
相关产品推荐

