Example #1
0
 def parse_vote_value(self, obj, key):
     """ Raises a ValidationError on incorrect values, including None """
     if key not in obj:
         raise ValidationError({"detail": f"The field {key} is required"})
     field = DecimalField(min_value=-2, max_digits=15, decimal_places=6)
     value = field.to_internal_value(obj[key])
     if value < 0 and value != -1 and value != -2:
         raise ValidationError({
             "detail":
             "No fractional negative values allowed, only the special values -1 and -2"
         })
     return value
class AssignmentAllPollSerializer(ModelSerializer):
    """
    Serializer for assignment.models.AssignmentPoll objects.

    Serializes all polls.
    """
    options = AssignmentOptionSerializer(many=True, read_only=True)
    votes = ListField(child=DictField(
        child=DecimalField(max_digits=15, decimal_places=6, min_value=-2)),
                      write_only=True,
                      required=False)
    has_votes = SerializerMethodField()

    class Meta:
        model = AssignmentPoll
        fields = (
            'id', 'pollmethod', 'description', 'published', 'options',
            'votesabstain', 'votesno', 'votesvalid', 'votesinvalid',
            'votescast', 'votes', 'has_votes', 'assignment'
        )  # js-data needs the assignment-id in the nested object to define relations.
        read_only_fields = ('pollmethod', )
        validators = (default_votes_validator, )

    def get_has_votes(self, obj):
        """
        Returns True if this poll has some votes.
        """
        return obj.has_votes()

    @transaction.atomic
    def update(self, instance, validated_data):
        """
        Customized update method for polls. To update votes use the write
        only field 'votes'.

        Example data for a 'pollmethod'='yna' poll with two candidates:

            "votes": [{"Yes": 10, "No": 4, "Abstain": -2},
                      {"Yes": -1, "No": 0, "Abstain": -2}]

        Example data for a 'pollmethod' ='yn' poll with two candidates:
            "votes": [{"Votes": 10}, {"Votes": 0}]
        """
        # Update votes.
        votes = validated_data.get('votes')
        if votes:
            options = list(instance.get_options())
            if len(votes) != len(options):
                raise ValidationError({
                    'detail':
                    _('You have to submit data for %d candidates.') %
                    len(options)
                })
            for index, option in enumerate(options):
                if len(votes[index]) != len(instance.get_vote_values()):
                    raise ValidationError({
                        'detail':
                        _('You have to submit data for %d vote values.') %
                        len(instance.get_vote_values())
                    })
                for vote_value, vote_weight in votes[index].items():
                    if vote_value not in instance.get_vote_values():
                        raise ValidationError({
                            'detail':
                            _('Vote value %s is invalid.') % vote_value
                        })
                instance.set_vote_objects_with_values(option,
                                                      votes[index],
                                                      skip_autoupdate=True)

        # Update remaining writeable fields.
        instance.description = validated_data.get('description',
                                                  instance.description)
        instance.published = validated_data.get('published',
                                                instance.published)
        instance.votesabstain = validated_data.get('votesabstain',
                                                   instance.votesabstain)
        instance.votesno = validated_data.get('votesno', instance.votesno)
        instance.votesvalid = validated_data.get('votesvalid',
                                                 instance.votesvalid)
        instance.votesinvalid = validated_data.get('votesinvalid',
                                                   instance.votesinvalid)
        instance.votescast = validated_data.get('votescast',
                                                instance.votescast)
        instance.save()
        return instance
Example #3
0
class AssignmentPollSerializer(BasePollSerializer):
    """
    Serializer for assignment.models.AssignmentPoll objects.

    Serializes all polls.
    """

    amount_global_no = DecimalField(max_digits=15,
                                    decimal_places=6,
                                    min_value=-2,
                                    read_only=True)
    amount_global_abstain = DecimalField(max_digits=15,
                                         decimal_places=6,
                                         min_value=-2,
                                         read_only=True)

    class Meta:
        model = AssignmentPoll
        fields = (
            "assignment",
            "description",
            "pollmethod",
            "votes_amount",
            "allow_multiple_votes_per_candidate",
            "global_no",
            "amount_global_no",
            "global_abstain",
            "amount_global_abstain",
        ) + BASE_POLL_FIELDS
        read_only_fields = ("state", )

    def update(self, instance, validated_data):
        """ Prevent updating the assignment """
        validated_data.pop("assignment", None)
        return super().update(instance, validated_data)

    def norm_100_percent_base_to_pollmethod(self,
                                            onehundred_percent_base,
                                            pollmethod,
                                            old_100_percent_base=None):
        """
        Returns None, if the 100-%-base must not be changed, otherwise the correct 100-%-base.
        """
        if pollmethod == AssignmentPoll.POLLMETHOD_YN and onehundred_percent_base in (
                AssignmentPoll.PERCENT_BASE_VOTES,
                AssignmentPoll.PERCENT_BASE_YNA,
        ):
            return AssignmentPoll.PERCENT_BASE_YN
        if (pollmethod == AssignmentPoll.POLLMETHOD_YNA and
                onehundred_percent_base == AssignmentPoll.PERCENT_BASE_VOTES):
            if old_100_percent_base is None:
                return AssignmentPoll.PERCENT_BASE_YNA
            else:
                if old_100_percent_base in (
                        AssignmentPoll.PERCENT_BASE_YN,
                        AssignmentPoll.PERCENT_BASE_YNA,
                ):
                    return old_100_percent_base
                else:
                    return pollmethod
        if (pollmethod == AssignmentPoll.POLLMETHOD_VOTES and
                onehundred_percent_base in (AssignmentPoll.PERCENT_BASE_YN,
                                            AssignmentPoll.PERCENT_BASE_YNA)):
            return AssignmentPoll.PERCENT_BASE_VOTES
        return None