DuVale / django-voting

Automatically exported from code.google.com/p/django-voting
Other
0 stars 0 forks source link

get_top alternative #10

Open GoogleCodeExporter opened 9 years ago

GoogleCodeExporter commented 9 years ago
This manager was realized by me. I think it is more flexible alternative
for get_top.

Original issue reported on code.google.com by rtolkach...@gmail.com on 7 Feb 2008 at 12:41

Attachments:

GoogleCodeExporter commented 9 years ago
Beautiful! Exactly what I was looking for.

Original comment by aa56...@gmail.com on 1 Jul 2009 at 9:09

GoogleCodeExporter commented 9 years ago
Love it! Works beautifully! I vote for this to be included in the project.

Original comment by maggon on 8 Nov 2009 at 9:02

GoogleCodeExporter commented 9 years ago
hi, thanks 
but can you explain how to plug this in properly?

Original comment by vallet...@gmail.com on 24 Oct 2010 at 2:13

GoogleCodeExporter commented 9 years ago
I know this is probably too late for some people, but I hope this answer helps 
others:

http://stackoverflow.com/questions/11073698/how-do-you-join-two-tables-using-dja
ngo-without-using-raw-sql/11233143#11233143

I was able to figure out the solution using a patch as described here:

http://code.google.com/p/django-voting/issues/detail?id=10

The difference was that I extracted the following lines:

        def select_score(self):
        """ Add vote scores for objects in resoultset """
        from django.contrib.contenttypes.models import ContentType
        model_type = ContentType.objects.get_for_model(self.model)
        table_name = self.model._meta.db_table
        print type(model_type)
        print model_type.id
        return self.extra(select={'score': 'SELECT SUM(vote) FROM votes WHERE content_type_id=%i AND object_id=%s.id' % (int(model_type.id), table_name)})

And added them to the **voting/managers.py** file as so:

    class VoteManager(models.Manager):
    def get_score(self, obj):
        """
        Get a dictionary containing the total score for ``obj`` and
        the number of votes it's received.
        """
        ctype = ContentType.objects.get_for_model(obj)
        result = self.filter(object_id=obj._get_pk_val(),
                             content_type=ctype).extra(
            select={
                'score': 'COALESCE(SUM(vote), 0)',
                'num_votes': 'COALESCE(COUNT(vote), 0)',
        }).values_list('score', 'num_votes')[0]

        return {
            'score': int(result[0]),
            'num_votes': int(result[1]),
        }

Then In my **topic.views.py** I added the following:

    from voting.managers import VoteManager
    def index(request):
    queryset = Topic.objects.select_score().order_by('-score')
    paginator = Paginator(queryset, 3) # Show 25 contacts per page

    page = request.GET.get('page')
    try:
        topic_list = paginator.page(page)
    except PageNotAnInteger:
        # If page is not an integer, deliver first page.
        topic_list = paginator.page(1)
    except EmptyPage:
        #If page is out of range (e.g. 9999), deliver last page of results.
        topic_list = paginator.page(paginator.num_pages)

    c = Context({
    'topic_list': topic_list,
    'request': request
    })
    return render_to_response('idea/index.html', c, context_instance=RequestContext(request))

Lastly, in my index.html I added the following lines slightly deviating from 
the original example provided for users:

    {% load voting_tags %}
    {% votes_by_user user on topic_list as vote_dict %}
    {% scores_for_objects topic_list as score_dict %}

    <table id="voting_table" class="list">
    <tbody>
      {% for link in topic_list %}
    <td class="vote">

    {% dict_entry_for_item link from vote_dict as vote %}
    {% dict_entry_for_item link from score_dict as score %}

    <div>    
     <form class="linkvote" id="linkup{{ link.id }}"{% if vote and vote.is_upvote %} action="{% url link_vote object_id=link.id, direction="clear" %}"{% else %} action="{% url link_vote object_id=link.id, direction="up" %}"{% endif %} method="POST">
        <input type="image" id="linkuparrow{{ link.id }}" src="{{ STATIC_URL }}images/aup{% if vote and vote.is_upvote %}mod{% else %}grey{% endif %}.png">
        {% csrf_token %}
        <input type="hidden" name="next" value="{{ request.get_full_path }}"/>
        {% else %}

      </form>

           <div id="link_score">{{ score.score|default:0 }}</div>

      <form class="linkvote" id="linkdown{{ link.id }}" {% if vote and vote.is_downvote %} action="{% url link_vote object_id=link.id, direction="clear" %}"{% else %} action="{% url link_vote object_id=link.id, direction="down" %}"{% endif %} method="POST">
      {% csrf_token %}
        <input type="image" id="linkdownarrow{{ link.id }}" src="{{ STATIC_URL }}images/adown{% if vote and vote.is_downvote %}mod{% else %}grey{% endif %}.png">
         <input type="hidden" name="next" value="{{ request.get_full_path }}"/>

    </td>
    <td class="item">
      <a id="link_title" href="{{ link.id }}">{{ link.title|escape }}</a></h2>
      <p class="details">
        <span class="score" id="linkscore{{ link.id }}"
              title="after {{ score.num_votes|default:0 }} vote{{ score.num_votes|default:0|pluralize }}">
        </span>
        posted {{ link.date_created|timesince }} ago by
        <span class="user"><a href="../users/{{ link.user.id }}/">{{ link.owner|escape }}</a></span>
    {% get_comment_count for link as comment_count %}
        <span id="comment_score" class="comment_details"> {{ comment_count }} comment{{ comment_count|pluralize }}</span>
      </p>
    </td>
    </tr>{% endfor %}
    </tbody>
      <td>
        <div id="paginator" class="pagination">
        <span class="step-links">
            {% if topic_list.has_previous %}
                <a href="?page={{ topic_list.previous_page_number }}">previous</a>
        {% endif %}
        {% if topic_list.has_next %}
            <a href="?page={{ topic_list.next_page_number }}">next</a>
        {% endif %}
        </span>
        </div>
      </td>
    </table>

I really hopes this helps someone else. Sorry for not posting the solution 
sooner. Hopefully someone can improve this by getting rid of the SQL all 
together from the VoteManager, but I need to move forward.

Original comment by jcostell...@gmail.com on 27 Jun 2012 at 6:57

GoogleCodeExporter commented 9 years ago
I almost forgot! If you would like the list to sort in an order like 
2,1,0,-1,-2 make sure to set the vote object value upon submitting whatever 
object you are creating.

def submit_topic(request):

    if request.method == 'POST':
        post_topic = PosttopicForm(request.POST)
        owner = request.user
        if post_topic.is_valid():
            topic = post_topic.save(commit=False)
            topic.owner = request.user
            topic.save()
            vote = Vote(vote='0', user = request.user, content_type_id=10, object_id=topic.pk)
            vote.save()
            url = reverse('topic', args=[topic.pk, topic.slug])
            return HttpResponseRedirect(url)
    else:
        post_topic = PosttopicForm()

    c = Context({
        'form': post_topic,
        'user': request.user,
        'request': request,
   })

    return render_to_response('topic/submit.html', c, context_instance=RequestContext(request))

Original comment by jcostell...@gmail.com on 27 Jun 2012 at 7:05