[Answered ]-Ajax post data in django1.5 ListView

2👍

I can’t tell you how much I learned by looking at the class based view source code. Once you’ve seen it, it becomes very easy to modify your class object to do what you want. In your case, if you add a post method to your class, it will be called in the event of a post to the url mapped to the view.

def post( self, request, *args **kwargs ):
  # receive the post, process the rating, return your JSON response

In response to your comments

Since you’re wanting users to be able to upvote/downvote from a ListView, you will need some way of identifying the post being voted on to the POST view which handles the request.

So if you were to send the id of the blogpost along with the vote, you could grab that model and update it accordingly.

assuming a model like this

class BlogPost( models.Model ):
  upvotes=models.IntegerField( default=0 )
  downvotes=models.IntegerField( default=0 )

  def get_score( self ):
    return self.upvotes - self.downvotes

  score=property( get_score )

yourtemplate.html

{% for post in object_list %}
 <div class="blogpost" data-pk="{{post.pk}}">
  <span class="score">{{post.score}}</span>
  <a class="upvote" href="#">Upvote</a>
  <a class="downvote" href="#">Downvote</a>
 </div>
{% endfor %}

yourjavascript.js

$('.blogpost').on( 'click', '.upvote,.downvote', function( e ){
  e.preventDefault();
  var id=$( this ).closest('.blogpost').data('pk'),
  upvote=$( this ).is('.upvote'),
  xhr=$.ajax({
    url: location.href, 
    type: 'post',
    data:{ id: id, upvote: upvote ? 1 : 0 },
    dataType: 'json'
  });
  xhr.done( function( data ){
     // successful submission
  });
});

views.py

class AwesomeDisplayListView(JSONResponseMixin,ListView):
  model = BlogPost
  template_name = "awesome_list.html"
  paginate_by = '15'
  context_object_name = "searchres" 

  def post( self, request, *args, **kwargs ):
    id=request.POST.get('id')
    upvote=int( request.POST.get('upvote') )
    blogpost=BlogPost.objects.get( pk=id )
    if upvote:
      blogpost.upvotes=blogpost.upvotes + 1
    else:
      blogpost.downvotes=blogpost.downvotes + 1
    blogpost.save()
    return http.HttpResponse( json.dumps({ 'score': blogpost.score }) )

To expand further on my last comment, a Rating model might make this easier.

class BlogPost( models.Model ):
  title=models.CharField( max_length=100 )
  def get_score( self ):
    return self.ratings.filter( up=True ).count() - self.ratings.filter( up=False ).count()

  score=property( get_score )


class Rating( models.Model ):
  blogpost=models.ForeignKey( BlogPost, related_name="ratings" )
  user=models.ForeignKey( User )
  up=models.BooleanField( default=True )

  class Meta:
    unique_together=('blogpost','user',)

Then in your post view

def post( self, request, *args, **kwargs ):
  id=request.POST.get('id')
  upvote=bool( int( request.POST.get('upvote') ) )
  blogpost=BlogPost.objects.get( pk=id )
  rating, is_new=Rating.objects.get_or_create( user=request.user, blogpost=blogpost )
  if rating.up != upvote:
    rating.up=upvote
    rating.save()

Leave a comment