1

所以,我有一个带有博客文章的小型博客应用程序(这里是 django 新手),并且我希望对这些项目中的每一个都包括一个“评级”(类似于 stackoflow 上的向上/向下)。所以,我拥有的是 ListView 中基于 ajax 的 GET - 但我现在意识到我需要 POST 来“修改”这个评级数据。我一直在寻找从 django ListView 发布数据,但我无法看到如何做到这一点。当前的 GET 代码是所有博客文章(分页)的列表视图,如下所示:

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

    def get_context_data(self, **kwargs):
        print "this is get_context_data"
        context = super(SearchDisplayListView, self).get_context_data(**kwargs)
        q = self.request.GET.get('q')
        context['searchq'] = q
        return context

    def get_queryset(self):
        print "this is get_queryset"
                # get some queryset
        return queryset 

    def render_to_response(self, context):
        if self.request.is_ajax():
            obj = {'name':'ajax', 'birthday':'may'}
            return JSONResponseMixin.render_to_response(self, obj)
        else:
            return ListView.render_to_response(self, context)

上面的代码可以很好地将数据(“obj”)获取到模板中,并且我能够呈现博客文章和 GET ajax,但是,我想做的是发布数据,以便:[1] 评级是从当前值增加 1 [2] 特定操作(点击投票),需要 login_required。

我想知道是否有人可以指出我正确的方向来做到这一点。我已经用谷歌搜索了这个问题,人们似乎建议组合 Mixins - 但是,不确定是否应该是这种情况。

谢谢。

4

1 回答 1

2

通过查看基于类的视图源代码,我无法告诉您我学到了多少。一旦你看到它,就很容易修改你的类对象来做你想做的事。在您的情况下,如果您post向您的类添加一个方法,它将在发布到映射到视图的 url 时被调用。

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

回应您的评论

由于您希望用户能够从 ListView 投票/否决,因此您需要某种方式来识别被投票到处理请求的 POST 视图的帖子。

因此,如果您将博文的 id 与投票一起发送,您可以获取该模型并相应地更新它。

假设这样的模型

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 )

你的模板.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 %}

你的javascript.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
  });
});

视图.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 }) )

为了进一步扩展我的上一条评论,评级模型可能会使这更容易。

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',)

然后在您的帖子视图中

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()
于 2013-03-07T16:26:45.723 回答