ejplatform/ej-conversations

View on GitHub
src/ej_conversations/models/vote.py

Summary

Maintainability
A
0 mins
Test Coverage
from django.conf import settings
from django.core.exceptions import ValidationError
from django.db import models
from django.utils.translation import ugettext_lazy as _

VOTING_ERROR = (lambda value: ValueError(
    f"vote should be one of 'agree', 'disagree' or 'skip', got {value}")
)


class Vote(models.Model):
    """
    A single vote cast for a comment.
    """
    # Be aware this is the opposite of polis. Eg. in polis, agree is -1.
    AGREE = 1
    SKIP = 0
    DISAGREE = -1

    VOTE_CHOICES = (
        (AGREE, _('Agree')),
        (SKIP, _('Skip')),
        (DISAGREE, _('Disagree')),
    )
    VOTE_NAMES = {
        AGREE: 'agree',
        DISAGREE: 'disagree',
        SKIP: 'skip',
    }
    VOTE_VALUES = {v: k for k, v in VOTE_NAMES.items()}

    author = models.ForeignKey(
        settings.AUTH_USER_MODEL,
        related_name='votes',
        on_delete=models.PROTECT,
    )
    comment = models.ForeignKey(
        'Comment',
        related_name='votes',
        on_delete=models.CASCADE,
    )
    created = models.DateTimeField(
        _('Created at'),
        auto_now_add=True,
    )
    value = models.IntegerField(
        _('Vote value'),
        choices=VOTE_CHOICES,
        help_text=_(
            'Numeric values: (disagree: -1, skip: 0, agree: 1)'
        ),
    )

    class Meta:
        unique_together = ('author', 'comment')

    @classmethod
    def normalize_vote(cls, value):
        """
        Normalize numeric and string values to the correct vote value that
        should be stored in the database.
        """
        if value in cls.VOTE_NAMES:
            return value
        try:
            return cls.VOTE_VALUES[value]
        except KeyError:
            raise VOTING_ERROR(value)

    def clean(self, *args, **kwargs):
        if self.comment.is_pending:
            msg = _('non-moderated comments cannot receive votes')
            raise ValidationError(msg)