I have a working django voting system using up and down keypresses on entries in a database.
I need to have the {{ entry.score }} refresh on the page without a reload, as there will be other entries on the page. The {{ entry.text }} can refresh but needs to stay as the same entry until a different keypress selects a different entry.
I'm trying to do it with ajax, but get a 500 Internal Server Error and no refresh,
GET http://127.0.0.1:8000/voteup/?voteid=30 500 (INTERNAL SERVER ERROR) jquery.min.js:4
send jquery.min.js:4
n.extend.ajax jquery.min.js:4
n.(anonymous function) jquery.min.js:4
(anonymous function) (index):76
n.event.dispatch jquery.min.js:3
r.handle
even though the vote goes through correctly...
(index):76 in voting.html is: $.get("/voteup/", args).done(function(data) {
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>
var data = '#Vote';
var url = "/voting/";
$(document).ready(function() {
$("#voteid").bind("keydown", function(e) { //input #submit?????
if (e.keyCode == 38) {
var text = $("#voteid").val();
var args = {'voteid':text};
$.get("/voteup/", args).done(function(data) {
console.log("message: " + data);
$.ajax({
url: url,
data: data,
dataType: 'html',
success: function(data){
$(this).html(data); //this?
}
});
});
return false;
}
});
});
</script>
{% endfor %}
</div>
</div>
</div>
views.py
def index(request):
context = { # actually one item, command from extended object manager
'voting_entry_list': Entry.objects.unvoted_or_random(),
}
return render(request, 'entries/index.html', context);
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')
e = Entry.objects.unvoted_or_random()
context = {'voting_entry_list': e,}
if request.method=='GET':
v = Entry.objects.get(pk=voting_id)
v.score +=1
v.voted=True
v.save()
context = {'voting_entry_list': v,}
else:
pass
return render(request, 'entries/voting.html', context);
Models.py
class EntryManager(models.Manager): #a basic extention to the model basemanager to insert new sorting
def unvoted_or_random(self): # command definition uses models input
unvoted_entries = self.filter(voted = False).order_by('-pub_date') # sorted by youngest unvoted entries from any user
voted_entries = self.filter(voted = True).order_by('?') # if no unvoted entries, voted boolean enables random selection '?'
if unvoted_entries: # for boolean unvoted
return unvoted_entries[:1] # return latest
else: # for boolean voted
return voted_entries[:1] # return random
I just had a session with a Phd student at the University, and he put me on the right track.
The basic issue I was having was about the philosophy of using Jquery and Ajax, something I found hard to glean from manuals and online support, which I found to be opaque on the very basics for simple tasks. To that end, I will present the final code here in the hopes it helps people starting out with a similar simple voting system.
Thanks to Refresh a div in Django using JQuery and AJAX Reload entire page in Ajax on Django? How to correctly refresh a div using Jquery/Ajax in a Django template Passing list of values to django view via jQuery ajax call For bits and pieces...
Voting refresh with no change of entry (button mashing)
My main problem was what I did for the url and data. It turns out I had the wrong end of the stick. Data in my case is the return from the views .get (I thought it was the entry id that I had to pass to the refresh) , and I didn't need to define the url for the very simple system I was making.
So This:
voting.html
Became This:
To refresh the scores as they are voted on. Span in the href above that code allowed me to access the score:
And the only other thing I had to do was add this to views in voteup(request) or votedown(request) when I accessed the entry models and added the vote:
views.py
This takes care of the vote up and down. When you button mash the up and down arrows, the entry stays the same, but the votes are refreshed from views after being saved to database.
Key to change entry with refresh
To change the entry (to a new, random entry), the .get for the right arrow key returns a string with the id, text and score of a random entry;
views.py
Which voting.html splits and refreshes text and score, and changes the currentid:
voting.html
So that's the main changes. I include the full(ish) code below in hope it helps someone;
voting.html
views.py