在 Google App Engine 中,我们在为博客文章创建投票按钮时可能会遇到以下问题:
-
问题描述:当用户点击投票按钮时,会发送一个 POST 请求到服务器,服务器收到请求后,会更新数据库中的文章投票数,然后重新渲染整个页面。如果用户在此过程中刷新页面,就会看到浏览器的确认表单提交警报。
-
具体代码:
class Latest(Handler):
def get(self):
posts = recent_posts()
qt = memcache.get('recent_posts_qt')
if qt:
qt = time.time() - qt
self.render('latest.html', articles = posts, qt = qt)
def post(self):
post_id = int(self.request.get("id"))
q = AllPost.get_by_id(post_id)
q.votes += 1
q.put()
time.sleep(0.5)
update = recent_posts(update=True) # for memcache
posts = db.GqlQuery("SELECT * FROM AllPost ORDER BY created DESC LIMIT 10")
posts = list(posts)
self.render('latest.html', articles=posts)
- 问题根源:刷新页面会再次发送 POST 请求,导致服务器再次更新数据库和重新渲染页面,从而触发浏览器的表单提交确认警报。
解决方案
为了解决这个问题,我们可以使用 AJAX 来实现投票功能。AJAX(Asynchronous JavaScript and XML)是一种在无需重新加载整个页面的情况下与服务器通信的技术。通过使用 AJAX,我们可以将投票请求发送到服务器,服务器更新数据库后立即返回结果,而无需重新渲染页面。
- 解决方法:
<div class="article-votes">
Votes: <span id="vote-count">{{ item.votes }}</span>
<button id="vote-button">Vote+</button>
</div>
const voteButton = document.getElementById('vote-button');
voteButton.addEventListener('click', () => {
const postId = {{ item.key().id() }};
const voteCountElement = document.getElementById('vote-count');
const request = new XMLHttpRequest();
request.open('POST', '/vote');
request.setRequestHeader('Content-Type', 'application/json');
request.send(JSON.stringify({ postId }));
request.onload = () => {
if (request.status === 200) {
const data = JSON.parse(request.responseText);
voteCountElement.textContent = data.voteCount;
} else {
alert('Error voting for post.');
}
};
});
@app.route('/vote', methods=['POST'])
def vote():
data = request.get_json()
post_id = data['postId']
post = AllPost.get_by_id(post_id)
post.votes += 1
post.put()
return json.dumps({
'voteCount': post.votes
})
以上代码可以通过 AJAX 发送投票请求到服务器,服务器收到请求后更新数据库中的文章投票数,然后返回更新后的投票数,而无需重新渲染页面。这样就可以避免刷新页面时触发浏览器的表单提交确认警报。
代码例子
以上代码实现了使用 AJAX 来更新投票数的功能。用户点击投票按钮时,会触发一个 AJAX 请求,该请求将把投票数和帖子 ID 发送到服务器。服务器收到请求后,更新数据库中的投票数,然后以 JSON 格式返回更新后的投票数。客户端收到服务器的响应后,更新界面的投票数,无需重新渲染整个页面。