Commit 95060813 authored by luxcem's avatar luxcem

up and down votes

parent 7f4d4bec
from core.apps import CoreConfig
def test_init():
assert CoreConfig.name == 'core'
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.contrib.auth.models import User
class UnDVotes(models.Model):
"""
Up and down vote model
"""
user = models.ForeignKey(
User,
on_delete=models.CASCADE,
)
#: Upvote, True for upvote, false for downvote
score = models.IntegerField(default=True)
# 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")
def __str__(self):
return "{}:{}:{}".format(self.user, 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)
def upvote(self, user):
diff_score = 0
try:
# Already voted content
vote = self.und_votes.get(user=user)
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, user=user, score=1)
vote.save()
diff_score = 1
self.__class__.objects.filter(id=self.id).update(
und_score=F("und_score") + diff_score)
def downvote(self, user):
diff_score = 0
try:
# Already voted content
vote = self.und_votes.get(user=user)
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, user=user, score=-1)
vote.save()
diff_score = -1
# 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)
def update_und_score(self):
"""Reset score to the correct count (should not be necessary)"""
score = self.und_votes.aggregate(Sum("score"))["score__sum"] or 0
# Update self score, use update and filter to avoid triggering signals
self.__class__.objects.filter(id=self.id).update(und_score=score)
class Meta:
abstract = True
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