Django:可以在模板中对对象投票和ID进行div ajax刷新,而不去视图吗?
我在Django中有一个投票模板。它一次只显示一个来自SQLite3数据库的条目,当我通过按键进行投票时,投票结果会保存在数据库中,然后投票模板会重新加载,视图会提供一个新的随机条目(模型管理器将随机条目传递给视图)。
我的理想情况是:我希望投票模板能显示三个不同的条目。- 3个不同的按键可以对这3个条目进行投票,但只会刷新它们的投票计数,而不会替换条目文本。- 3个不同的按键可以单独选择新的随机条目。目前,我只在尝试使用1个条目。
复杂的方法:我想我应该把被投票条目的ID从HTML传递到视图中的投票函数,然后再把这个ID传递到views.py中的投票模板,以便只刷新分数,而不是用不同的条目替换。
简单的方法(更喜欢这种!):经过进一步的研究和查看以下几个StackOverflow的问题:使用JQuery和AJAX在Django中刷新一个div 在Django中用Ajax重新加载整个页面? 如何在Django模板中正确刷新一个div 通过jQuery Ajax调用将值列表传递给Django视图。
我觉得问题的关键在于:
我想在投票页面上刷新条目的投票数,当我对它们进行投票时。为了避免过于复杂,我认为可以在模板中更新div以进行投票更新,而不是重新加载整个投票.html,这样就不会更换条目。
要更换显示的条目,我可以在按下另一个按钮时切换访问的条目ID并刷新div(从数据库获取新条目)吗?我原以为必须把条目ID传递给views.py,但也许我可以在模板中完成所有操作?如果我可以在不出错的情况下上下切换数据库条目,就不需要从视图中获取随机条目。
为此,我已经修改了下面的voting.html代码:
$.ajax({
success: function() {
$(this).html();
}
在按钮按下后。它允许投票,但不刷新条目。我从一些StackOverflow的问题中了解到,我需要传入一些值或一个div来更新,但在这样做时遇到了困难。我一直在尝试传入div #Vote,但脚本在div中间,而不是在外面。尝试传入voteid似乎也不行,实际上还阻止了投票;
$.ajax({
data: {'voteid': text}
success: function(data) {
$(this).html(data);
}
});
有人能帮我做到这一点吗?
我觉得我快到了 - 这里有一些代码片段:
models.py
class EntryManager(models.Manager): # TO RETURN ONE RANDOM ENTRY
def random(self):
random_entries = self.filter(voted = True).order_by('?') # random entry
return random_entries[:1] # return latest
voting.html
<div class = "table">
<div id="Vote" class = "vote">
<div style="text-align: left">
{% for entry in voting_entry_list %}
<li><a href="/entries/{{ entry.id }}/">{{ entry.text }} {{ entry.score }}</a></li>
<p>
<input type="submit" id="voteid" name='voteid' value="{{ entry.id }}" autofocus value="" onfocus="this.value = this.value;" class = "transparent"/>
<script>
$(document).ready(function() {
$("#voteid").bind("keydown", function(e) { //input type=id above
if (e.keyCode == 38) {
var text = $("#voteid").val();
var args = {'voteid':text};
$.get("/voteup/", args).done(function(data) {
console.log("message: " + data);
//location.reload();
$.ajax({
success: function() {
$(this).html();
}
});
});
return false;
}
if (e.keyCode == 40) {
var text = $("#voteid").val();
var args = {'voteid':text};
$.get("/votedown/", args).done(function(data) {
console.log("message: " + data);
//location.reload();
$.ajax({
success: function() {
$(this).html();
}
});
});
return false;
}
});
});
</script>
{% endfor %}
</div>
</div>
</div>
views.py
def voting(request):
context = {
'voting_entry_list': Entry.objects.random(),
}
return render(request, 'entries/voting.html', context);
def voteup(request):
voting_id = request.GET.get('voteid')
if request.method=='GET':
v = Entry.objects.get(pk=voting_id)
v.score +=1
v.voted=True
v.save()
else:
pass
context = {
'voting_entry_list': v,
}
return render('entries/voting.html', {'voting_entry_list': v})
# not working? no refresh ^
# Tried these;
# return render_to_response('voting.html', RequestContext(request, {'voting_entry_list': v})) #no refresh
# return render(request, 'entries/voting.html', context); #no refresh
# return HttpResponse('done') # Only on template reload
# return render('voting.html', context); #no refresh
# return HttpResponseRedirect('entries/voting.html') #no refresh
1 个回答
我不明白你为什么说Django不适合处理异步请求。其实它处理这些请求完全没问题:这些请求和普通请求在本质上没有什么不同。不过,对于你这个非常简单的任务来说,其实根本不需要用到这些异步的东西,或者你提到的那些工具:你根本不想要异步请求。
这里有几个问题。首先,你的大部分尝试似乎都是在渲染整个 voting.html 模板。你并不想这样,对吧?你只想渲染其中的一部分,也就是包含你想要的投票的那部分。此外,你把一个单独的投票实例 v
作为 "voting_entry_list" 的上下文变量传递,这样在模板中尝试用 for 循环遍历这个列表时,就会出现异常,因为单个实例是不能被遍历的。如果你用浏览器的开发者工具查看 Ajax 的响应,你会发现你大多数尝试都会显示 "不可遍历" 的异常。
然后,还有你的JavaScript代码本身的问题。我完全不明白你为什么在两个处理函数中都放了 location.reload()
。这样会导致整个页面被刷新,发出一个全新的、非Ajax的请求到服务器,完全忽略了你已经收到的Ajax响应,并且刷新了整个页面。你应该做的是把在Ajax响应中得到的HTML插入到页面的合适位置,而不是刷新整个页面,这可以通过正常的jQuery DOM操作函数来实现。