Commit 2f24436a authored by luxcem's avatar luxcem

Change vote to use django-und

parent a8b051fc
from django.contrib import admin from django.contrib import admin
from .models import Article, UnDVotes from .models import Article
admin.site.register(Article) admin.site.register(Article)
admin.site.register(UnDVotes)
# -*- coding: utf-8 -*-
# Generated by Django 1.11 on 2017-04-25 15:00
from __future__ import unicode_literals
from django.db import migrations
class Migration(migrations.Migration):
dependencies = [
('rp', '0009_auto_20170423_1633'),
]
operations = [
migrations.RemoveField(
model_name='undvotes',
name='content_type',
),
migrations.RemoveField(
model_name='article',
name='und_score',
),
migrations.DeleteModel(
name='UnDVotes',
),
]
from .vote import UnDVotes, UnDVotedMixin # noqa
from .article import Article # noqa from .article import Article # noqa
from django.db import models from django.db import models
from django.utils.translation import ugettext_lazy as _ from django.utils.translation import ugettext_lazy as _
from taggit.managers import TaggableManager from taggit.managers import TaggableManager
from .vote import UnDVotedMixin
from newspaper import Article as ArticleParser from newspaper import Article as ArticleParser
from django_und.models import VoteMixin
STATUS_CHOICES = ( STATUS_CHOICES = (
...@@ -12,7 +13,7 @@ STATUS_CHOICES = ( ...@@ -12,7 +13,7 @@ STATUS_CHOICES = (
) )
class Article(UnDVotedMixin): class Article(VoteMixin):
url = models.URLField("URL") url = models.URLField("URL")
lang = models.CharField(_("Language"), max_length=50, null=True) lang = models.CharField(_("Language"), max_length=50, null=True)
metadata = models.TextField(_("Opengraph metadata"), blank=True, null=True) metadata = models.TextField(_("Opengraph metadata"), blank=True, null=True)
......
from django.db import models
from django.db.models import Sum, F
from django.contrib.contenttypes.fields import GenericForeignKey
from django.contrib.contenttypes.fields import GenericRelation
from django.contrib.contenttypes.models import ContentType
from django.utils.translation import ugettext_lazy as _
class UnDVotes(models.Model):
"""
Up and down vote model
"""
#: username
username = models.CharField(max_length=255, null=False)
#: Score of the vote
score = models.IntegerField(default=1)
# Django generic relation
content_type = models.ForeignKey(ContentType, on_delete=models.CASCADE)
object_id = models.PositiveIntegerField()
#: The Voted object
content_object = GenericForeignKey("content_type", "object_id")
class Meta:
verbose_name = _("Vote")
verbose_name_plural = _("Votes")
def __str__(self):
return "{}:{}:{}".format(
self.username, self.content_object, self.score)
class UnDVotedMixin(models.Model):
"""
A mixin to attach to a model that has up and down votes
"""
#: Votes
und_votes = GenericRelation(UnDVotes)
#: Score of the model
und_score = models.IntegerField(default=0)
und_score_up = models.IntegerField(default=0)
und_score_down = models.IntegerField(default=0)
class Meta:
abstract = True
def upvote(self, username):
diff_score = 0
try:
# Already voted content
vote = self.und_votes.get(username=username)
if vote.score == 1:
# Cancel previous upvote
vote.delete()
diff_score = -1
else:
# Previously downvoted
vote.score = 1
vote.save()
diff_score = 2
except:
vote = UnDVotes(content_object=self, username=username, score=1)
vote.save()
diff_score = 1
self.und_score += diff_score
self.und_score_up += diff_score
# Update self score, use update and filter to avoid triggering signals
self.__class__.objects.filter(id=self.id).update(
und_score=F("und_score") + diff_score,
und_score_up=F("und_score_up") + diff_score
)
def downvote(self, username):
diff_score = 0
try:
# Already voted content
vote = self.und_votes.get(username=username)
if vote.score == -1:
# Cancel previous downvote
vote.delete()
diff_score = 1
else:
# Previously upvoted
vote.score = -1
vote.save()
diff_score = -2
except:
vote = UnDVotes(content_object=self, username=username, score=-1)
vote.save()
diff_score = -1
self.und_score += diff_score
self.und_score_down += diff_score
# Update self score, use update and filter to avoid triggering signals
self.__class__.objects.filter(id=self.id).update(
und_score=F("und_score") + diff_score,
und_score_down=F("und_score_down") + diff_score
)
def update_und_score(self):
"""Reset score to the correct count (should not be necessary)"""
score_up = self.und_votes.filter(score=1).count()
score_down = self.und_votes.filter(score=-1).count()
score = score_up + score_down
self.und_score_up = score_up
self.und_score_down = score_down
self.und_score = score
# Update self score, use update and filter to avoid triggering signals
self.__class__.objects.filter(id=self.id).update(und_score=score)
from django.test import TestCase
from rp.models import Article from rp.models import Article
from rp.factories import ArticleFactory from rp.factories import ArticleFactory
from rp.apps import RpConfig from rp.apps import RpConfig
def test_init(): class TestVote(TestCase):
assert RpConfig.name == "rp" def setUp(self):
self.article = ArticleFactory()
def test_article():
article = ArticleFactory()
assert type(article) == Article
def test_votes():
article = ArticleFactory()
# Upvote
article.upvote("test_user")
article_db = Article.objects.get(id=article.id)
assert article.und_score == 1
assert article_db.und_score == 1
votes = article_db.und_votes.all()
assert len(votes) == 1
assert str(votes[0]) == "{}:{}:{}".format(
"test_user", str(article_db), 1)
# Upvote -> upvote
article.upvote("test_user")
article_db = Article.objects.get(id=article.id)
assert article.und_score == 0
assert article_db.und_score == 0
# 0 -> downvote
article.downvote("test_user")
article_db = Article.objects.get(id=article.id)
assert article.und_score == -1
assert article_db.und_score == -1
# Downvote -> Downvote
article.downvote("test_user")
article_db = Article.objects.get(id=article.id)
assert article.und_score == 0
assert article_db.und_score == 0
# Downvote -> Upvote
article.downvote("test_user")
article_db = Article.objects.get(id=article.id)
assert article.und_score == -1
assert article_db.und_score == -1
article.upvote("test_user")
article_db = Article.objects.get(id=article.id)
assert article.und_score == 1
assert article_db.und_score == 1
# Upvote -> Downwote def test_init(self):
article.downvote("test_user") assert RpConfig.name == "rp"
article_db = Article.objects.get(id=article.id)
assert article.und_score == -1
assert article_db.und_score == -1
article.update_und_score() def test_article(self):
article_db = Article.objects.get(id=article.id) assert type(self.article) == Article
assert article.und_score == -1
assert article_db.und_score == -1
from django.urls import reverse from django.urls import reverse
from django.test import TestCase from django.test import TestCase
from django.contrib.contenttypes.models import ContentType
from userprofile.factories import ProfileFactory from userprofile.factories import ProfileFactory
from rp.factories import ArticleFactory from rp.factories import ArticleFactory
...@@ -10,30 +9,25 @@ from rp.models import Article ...@@ -10,30 +9,25 @@ from rp.models import Article
class VoteViewTestCase(TestCase): class VoteViewTestCase(TestCase):
def setUp(self): def setUp(self):
self.article = ArticleFactory() self.article = ArticleFactory()
self.content_type = ContentType.objects.get_for_model(
self.article
).pk
self.profile = ProfileFactory() self.profile = ProfileFactory()
self.user = self.profile.user self.user = self.profile.user
self.client.force_login(self.user) self.client.force_login(self.user)
def test_votes(self): def test_votes(self):
url_upvote = reverse("und-upvote", kwargs={ url_upvote = reverse("api:article-upvote", kwargs={
"content_type": self.content_type, "pk": self.article.id
"object_id": self.article.id
}) })
url_downvote = reverse("und-downvote", kwargs={ url_downvote = reverse("api:article-downvote", kwargs={
"content_type": self.content_type, "pk": self.article.id
"object_id": self.article.id
}) })
response = self.client.get(url_upvote) response = self.client.post(url_upvote)
assert response.status_code == 200 assert response.status_code == 200
article_db = Article.objects.get(id=self.article.id) article_db = Article.objects.get(id=self.article.id)
assert article_db.und_score == 1 assert article_db.und_score == 1
response = self.client.get(url_downvote) response = self.client.post(url_downvote)
assert response.status_code == 200 assert response.status_code == 200
article_db = Article.objects.get(id=self.article.id) article_db = Article.objects.get(id=self.article.id)
assert article_db.und_score == -1 assert article_db.und_score == -1
...@@ -14,12 +14,12 @@ class UDList(ListView): ...@@ -14,12 +14,12 @@ class UDList(ListView):
"upvoted": queryset.filter( "upvoted": queryset.filter(
und_votes__username=self.request.user.username, und_votes__username=self.request.user.username,
und_votes__content_type=content_type, und_votes__content_type=content_type,
und_votes__score=1 und_votes__score__gt=0
).values_list("id", flat=True), ).values_list("id", flat=True),
"downvoted": queryset.filter( "downvoted": queryset.filter(
und_votes__username=self.request.user.username, und_votes__username=self.request.user.username,
und_votes__content_type=content_type, und_votes__content_type=content_type,
und_votes__score=-1 und_votes__score__lt=0
).values_list("id", flat=True) ).values_list("id", flat=True)
} }
return context return context
...@@ -16,6 +16,7 @@ DJANGO_APPS = [ ...@@ -16,6 +16,7 @@ DJANGO_APPS = [
CONTRIB_APPS = [ CONTRIB_APPS = [
"django_extensions", # http://django-extensions.readthedocs.io/ "django_extensions", # http://django-extensions.readthedocs.io/
"rest_framework", # http://www.django-rest-framework.org/ "rest_framework", # http://www.django-rest-framework.org/
"django_und", # https://github.com/luxcem/django_und
# https://github.com/philipn/django-rest-framework-filters # https://github.com/philipn/django-rest-framework-filters
# "rest_framework_filters", # "rest_framework_filters",
"taggit", "taggit",
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment