Skip to content

Commit

Permalink
Merge pull request #45 from shanbay/feature-support-vote-down
Browse files Browse the repository at this point in the history
Feature support vote down
  • Loading branch information
shellfly authored Feb 9, 2017
2 parents dffdd98 + 62e3bf3 commit eab8679
Show file tree
Hide file tree
Showing 15 changed files with 280 additions and 144 deletions.
7 changes: 7 additions & 0 deletions CHANGELOG.md
Original file line number Diff line number Diff line change
@@ -1,5 +1,12 @@
# Changelog

2.1.4(2017.02.09)
------------------
https://github.com/Beeblio/django-vote/tree/2.1.3

* Support vote down


2.1.2(2016.11.02)
------------------
https://github.com/Beeblio/django-vote/tree/2.1.2
Expand Down
36 changes: 21 additions & 15 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -25,44 +25,50 @@ INSTALLED_APPS = (
)
```

#### Add `VoteModel` to the model you want to vote

```python
from vote.models import VoteModel

class ArticleReview(VoteModel, models.Model):
...
```

#### Run migrate

```shell
manage.py makemigrations
manage.py migrate
```

#### Declare vote field to the model you want to vote

```python
from vote.managers import VotableManager

class ArticleReview(models.Model):
...
votes = VotableManager()
```

#### Use vote API

```python
review = ArticleReview.objects.get(pk=1)

# Adds a new vote to the object
# Up vote to the object
review.votes.up(user_id)

# Removes vote to the object
# Down vote to the object
review.votes.down(user_id)

# Removes a vote from the object
review.votes.delete(user_id)

# Check if the user already voted the object
review.votes.exists(user_id)

# Returns all instances voted by user
Review.votes.all(user_id)

# Returns the number of votes for the object
review.votes.count()

# Returns a list of users who voted and their voting date
review.votes.users()
review.votes.user_ids()


# Returns all instances voted by user
Review.votes.all(user_id)

```

``django-vote`` now requires Django 1.7 or greater. (for Django < 1.7, please install previous release `django-vote==1.1.3`)
23 changes: 16 additions & 7 deletions docs/api.rst
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@
The API
=======

After you've got your ``VotableManager`` added to your model you can start
After you've got your ``VoteModel`` added to your model you can start
playing around with the API.

.. class:: VotableManager([through=None, verbose_name="Votes", field_name='votes', extra_field=None])
Expand All @@ -11,30 +11,39 @@ playing around with the API.
:param field_name: The field name added to the query
:param extra_field: The field on your model. It will be updated when up or down

.. method:: up(user)
.. method:: up(user_id)

This adds a vote to an object by the ``user``. ``IntegrityError`` will be raised if the user has voted before::

>>> comments.votes.up(user)

.. method:: down(user)
.. method:: down(user_id)

Removes the vote from an object. No exception is raised if the user
doesn't have voted the object.

.. method:: delete(user_id)

.. method:: exists(user)
Removes the vote from an object. No exception is raised if the user
doesn't have voted the object.

.. method:: exists(user_id, action=UP)

Check if user has voted the instance before.

.. method:: all(user)
.. method:: all(user_id, action=UP)

Get all instances voted by the specify user.

.. method:: count()
.. method:: user_ids(action=UP)

Get all user_ids voted the instance

.. method:: count(action=UP)

The count of all votes for an object.

.. method:: annotate(queryset=None, user=None)
.. method:: annotate(queryset=None, user_id=None, reverse=True, sort=True)

Add annotation data to the ``queyset``

Expand Down
6 changes: 6 additions & 0 deletions docs/changelog.rst
Original file line number Diff line number Diff line change
@@ -1,6 +1,12 @@
Changelog
=========

2.1.4(2017.02.09)
------------------

* Support vote down


2.1.2(2016.11.02)
------------------

Expand Down
26 changes: 6 additions & 20 deletions docs/getting_started.rst
Original file line number Diff line number Diff line change
Expand Up @@ -9,32 +9,18 @@ To get started using ``django-vote`` simply install it with

Add ``"vote"`` to your project's ``INSTALLED_APPS`` setting.

Run::
./manage.py migrate

And then to any model you want vote on do the following::

from django.db import models

from vote.managers import VotableManager
from vote.models import VoteModel

class Comment(models.Model):
class Comment(VoteModel,models.Model):
# ... fields here
Run::

votes = VotableManager()



If you want to save number of votes directly on original model::

from django.db import models

from vote.managers import VotableManager

class Comment(models.Model):
# ... fields here
num_votes = models.PositiveIntegerField(default=0)
votes = VotableManager(extra_field='num_votes')
./manage.py makemigrations
./manage.py migrate
16 changes: 2 additions & 14 deletions test/models.py
Original file line number Diff line number Diff line change
@@ -1,23 +1,11 @@
from django.db import models
from vote.managers import VotableManager
from vote.models import VoteModel


# Create your models here.
class Comment(models.Model):
class Comment(VoteModel):
user_id = models.BigIntegerField()
content = models.TextField()
num_vote = models.IntegerField(default=0)
create_at = models.DateTimeField(auto_now_add=True)
update_at = models.DateTimeField(auto_now=True)

votes = VotableManager()


class CustomVoteComment(models.Model):
user_id = models.BigIntegerField()
content = models.TextField()
num_vote = models.PositiveIntegerField(default=0)
create_at = models.DateTimeField(auto_now_add=True)
update_at = models.DateTimeField(auto_now=True)

custom_votes = VotableManager(extra_field='num_vote')
64 changes: 36 additions & 28 deletions test/tests.py
Original file line number Diff line number Diff line change
@@ -1,8 +1,8 @@
from __future__ import absolute_import
from django.test import TestCase
from django.contrib.auth.models import User
from vote.models import Vote
from test.models import Comment, CustomVoteComment
from vote.models import Vote, UP, DOWN
from test.models import Comment


class VoteTest(TestCase):
Expand Down Expand Up @@ -34,32 +34,44 @@ def test_vote_up(self):
content="I'm a comment")

self.call_api('up', comment, self.user2.pk)
self.assertEqual(self.call_api('count', comment), 1)
self.assertEqual(self.call_api('count', comment, UP), 1)

# call up again, will not increase count
res = self.call_api('up', comment, self.user2.pk)
self.assertEqual(res, False)
self.assertEqual(self.call_api('count', comment), 1)
self.assertEqual(self.call_api('count', comment, UP), 1)

def test_vote_down(self):
comment = self.model.objects.create(user_id=self.user1.pk,
content="I'm a comment")

# no votes yet, no exception raised
self.assertEqual(self.call_api('count'), 0)
self.assertEqual(self.call_api('count', comment, DOWN), 0)
self.call_api('down', comment, self.user2.pk)
self.assertEqual(self.call_api('count', comment, DOWN), 1)

self.call_api('up', comment, self.user2.pk)
self.assertEqual(self.call_api('count', comment), 1)
self.assertEqual(self.call_api('count', comment, UP), 1)
self.call_api('down', comment, self.user2.pk)
self.assertEqual(self.call_api('count', comment), 0)
self.assertEqual(self.call_api('count', comment, DOWN), 1)

def test_vote_delete(self):
comment = self.model.objects.create(user_id=self.user1.pk,
content="I'm a comment")

self.call_api('up', comment, self.user2.pk)
self.assertEqual(self.call_api('count', comment, UP), 1)
self.call_api('delete', comment, self.user2.pk)
self.assertEqual(self.call_api('count', comment, UP), 0)

def test_vote_exists(self):
comment = self.model.objects.create(user_id=self.user1.pk,
content="I'm a comment")
self.assertFalse(self.call_api('exists', comment, self.user2.pk))
self.assertFalse(self.call_api('exists', comment, self.user2.pk,
UP))
self.call_api('up', comment, self.user2.pk)
self.assertTrue(self.call_api('exists', comment, self.user2.pk))
self.assertTrue(self.call_api('exists', comment,
self.user2.pk, UP))

def test_vote_all(self):
comment = self.model.objects.create(user_id=self.user1.pk,
Expand All @@ -81,7 +93,7 @@ def test_vote_count(self):

def test_user_ids(self):
comment = self.model.objects.create(user_id=self.user1.pk,
content="I'm a comment")
content="I'm a comment")
self.call_api('up', comment, self.user1.pk)
self.assertEqual(len(list(self.call_api('user_ids', comment))), 1)

Expand Down Expand Up @@ -116,7 +128,7 @@ def test_vote_annotate(self):
self.assertEqual(comments[-2].pk, comment1.pk)

for comment in comments:
self.assertTrue(hasattr(comment, 'num_votes'))
self.assertTrue(hasattr(comment, 'vote_score'))

# call annotate with queryset and user_id
comments = self.model.objects.filter(user_id=self.user1.pk)
Expand All @@ -126,15 +138,15 @@ def test_vote_annotate(self):
self.assertEqual(comments[1].pk, comment1.pk)

for comment in comments:
self.assertTrue(hasattr(comment, 'num_votes'))
self.assertTrue(hasattr(comment, 'is_voted'))
self.assertTrue(hasattr(comment, 'vote_score'))
self.assertTrue(hasattr(comment, 'is_voted_up'))
self.assertTrue(hasattr(comment, 'is_voted_down'))
if comment.pk in (comment1.pk, comment2.pk):
self.assertTrue(comment.is_voted)
self.assertTrue(comment.is_voted_up)
else:
self.assertFalse(comment.is_voted)
self.assertFalse(comment.is_voted_up)

def test_objects_with_status(self):
test_field = 'is_test_voted'
comments = [
self.model(
user_id=self.user1.pk,
Expand All @@ -154,27 +166,28 @@ def test_objects_with_status(self):
comment_ids = [comment2.id, comment1.id]

votes = getattr(self.model, self.field_name)
comments = votes.vote_by(self.user2.pk, ids=comment_ids,
field=test_field)
comments = votes.vote_by(self.user2.pk, ids=comment_ids)

self.assertEqual(comments[0].id, comment2.id)
for comment in comments:
self.assertTrue(hasattr(comment, test_field))
self.assertTrue(hasattr(comment, 'is_voted_up'))
self.assertTrue(hasattr(comment, 'is_voted_down'))

comment_ids = [comment1.id, comment2.id]

votes = getattr(self.model, self.field_name)
comments = votes.vote_by(self.user2.pk, ids=comment_ids,
field=test_field)
comments = votes.vote_by(self.user2.pk, ids=comment_ids)

self.assertEqual(comments[0].id, comment1.id)
for comment in comments:
self.assertTrue(hasattr(comment, test_field))
self.assertTrue(hasattr(comment, 'is_voted_up'))
self.assertTrue(hasattr(comment, 'is_voted_down'))


comments = votes.vote_by(self.user2.pk, queryset=Comment.objects.all())
for comment in comments:
self.assertTrue(hasattr(comment, 'is_voted'))
self.assertTrue(hasattr(comment, 'is_voted_up'))
self.assertTrue(hasattr(comment, 'is_voted_down'))

self.assertRaises(ValueError, lambda: votes.vote_by(self.user2.pk))

Expand All @@ -193,8 +206,3 @@ def test_vote_templatetag(self):
res = self.client.get('/comments/')
self.client.login(username=self.user1.username, password='111111')
self.client.get('/comments/')

class CustomVoteTest(VoteTest):
through = Vote
model = CustomVoteComment
field_name = 'custom_votes'
2 changes: 1 addition & 1 deletion vote/__init__.py
Original file line number Diff line number Diff line change
@@ -1,3 +1,3 @@
VERSION = (2, 1, 3)
VERSION = (2, 1, 4)

default_app_config = 'vote.apps.VoteAppConfig'
Loading

0 comments on commit eab8679

Please sign in to comment.