Django:可以在模板中对对象投票和ID进行div ajax刷新,而不去视图吗?

0 投票
1 回答
1127 浏览
提问于 2025-04-18 16:35

我在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 }}&nbsp{{ 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 个回答

1

我不明白你为什么说Django不适合处理异步请求。其实它处理这些请求完全没问题:这些请求和普通请求在本质上没有什么不同。不过,对于你这个非常简单的任务来说,其实根本不需要用到这些异步的东西,或者你提到的那些工具:你根本不想要异步请求。

这里有几个问题。首先,你的大部分尝试似乎都是在渲染整个 voting.html 模板。你并不想这样,对吧?你只想渲染其中的一部分,也就是包含你想要的投票的那部分。此外,你把一个单独的投票实例 v 作为 "voting_entry_list" 的上下文变量传递,这样在模板中尝试用 for 循环遍历这个列表时,就会出现异常,因为单个实例是不能被遍历的。如果你用浏览器的开发者工具查看 Ajax 的响应,你会发现你大多数尝试都会显示 "不可遍历" 的异常。

然后,还有你的JavaScript代码本身的问题。我完全不明白你为什么在两个处理函数中都放了 location.reload()。这样会导致整个页面被刷新,发出一个全新的、非Ajax的请求到服务器,完全忽略了你已经收到的Ajax响应,并且刷新了整个页面。你应该做的是把在Ajax响应中得到的HTML插入到页面的合适位置,而不是刷新整个页面,这可以通过正常的jQuery DOM操作函数来实现。

撰写回答