Exemple #1
0
class TopicSerializer(ModelSerializer):
    """
    Serializer for core.models.Topic objects.
    """
    agenda_type = IntegerField(write_only=True,
                               required=False,
                               min_value=1,
                               max_value=2)
    agenda_parent_id = IntegerField(write_only=True,
                                    required=False,
                                    min_value=1)
    agenda_comment = CharField(write_only=True,
                               required=False,
                               allow_blank=True)
    agenda_duration = IntegerField(write_only=True,
                                   required=False,
                                   min_value=1)
    agenda_weight = IntegerField(write_only=True, required=False, min_value=1)

    class Meta:
        model = Topic
        fields = (
            'id',
            'title',
            'text',
            'attachments',
            'agenda_item_id',
            'agenda_type',
            'agenda_parent_id',
            'agenda_comment',
            'agenda_duration',
            'agenda_weight',
        )

    def validate(self, data):
        if 'text' in data:
            data['text'] = validate_html(data['text'])
        return data

    def create(self, validated_data):
        """
        Customized create method. Set information about related agenda item
        into agenda_item_update_information container.
        """
        agenda_type = validated_data.pop('agenda_type', None)
        agenda_parent_id = validated_data.pop('agenda_parent_id', None)
        agenda_comment = validated_data.pop('agenda_comment', None)
        agenda_duration = validated_data.pop('agenda_duration', None)
        agenda_weight = validated_data.pop('agenda_weight', None)
        attachments = validated_data.pop('attachments', [])
        topic = Topic(**validated_data)
        topic.agenda_item_update_information['type'] = agenda_type
        topic.agenda_item_update_information['parent_id'] = agenda_parent_id
        topic.agenda_item_update_information['comment'] = agenda_comment
        topic.agenda_item_update_information['duration'] = agenda_duration
        topic.agenda_item_update_information['weight'] = agenda_weight
        topic.save()
        topic.attachments.add(*attachments)
        return topic
class TopicSerializer(ModelSerializer):
    """
    Serializer for core.models.Topic objects.
    """

    agenda_type = IntegerField(
        write_only=True, required=False, min_value=1, max_value=3, allow_null=True
    )
    agenda_parent_id = IntegerField(write_only=True, required=False, min_value=1)
    agenda_comment = CharField(write_only=True, required=False, allow_blank=True)
    agenda_duration = IntegerField(write_only=True, required=False, min_value=1)
    agenda_weight = IntegerField(write_only=True, required=False, min_value=1)

    class Meta:
        model = Topic
        fields = (
            "id",
            "title",
            "text",
            "attachments",
            "agenda_item_id",
            "agenda_type",
            "agenda_parent_id",
            "agenda_comment",
            "agenda_duration",
            "agenda_weight",
        )

    def validate(self, data):
        if "text" in data:
            data["text"] = validate_html(data["text"])
        return data

    def create(self, validated_data):
        """
        Customized create method. Set information about related agenda item
        into agenda_item_update_information container.
        """
        agenda_type = validated_data.pop("agenda_type", None)
        agenda_parent_id = validated_data.pop("agenda_parent_id", None)
        agenda_comment = validated_data.pop("agenda_comment", None)
        agenda_duration = validated_data.pop("agenda_duration", None)
        agenda_weight = validated_data.pop("agenda_weight", None)
        attachments = validated_data.pop("attachments", [])
        topic = Topic(**validated_data)
        topic.agenda_item_update_information["type"] = agenda_type
        topic.agenda_item_update_information["parent_id"] = agenda_parent_id
        topic.agenda_item_update_information["comment"] = agenda_comment
        topic.agenda_item_update_information["duration"] = agenda_duration
        topic.agenda_item_update_information["weight"] = agenda_weight
        topic.save(skip_autoupdate=True)
        topic.attachments.add(*attachments)
        inform_changed_data(topic)
        return topic
class AssignmentFullSerializer(ModelSerializer):
    """
    Serializer for assignment.models.Assignment objects. With all polls.
    """
    assignment_related_users = AssignmentRelatedUserSerializer(many=True,
                                                               read_only=True)
    polls = AssignmentAllPollSerializer(many=True, read_only=True)
    agenda_type = IntegerField(write_only=True,
                               required=False,
                               min_value=1,
                               max_value=3)
    agenda_parent_id = IntegerField(write_only=True,
                                    required=False,
                                    min_value=1)

    class Meta:
        model = Assignment
        fields = (
            'id',
            'title',
            'description',
            'open_posts',
            'phase',
            'assignment_related_users',
            'poll_description_default',
            'polls',
            'agenda_item_id',
            'agenda_type',
            'agenda_parent_id',
            'tags',
        )
        validators = (posts_validator, )

    def validate(self, data):
        if 'description' in data:
            data['description'] = validate_html(data['description'])
        return data

    def create(self, validated_data):
        """
        Customized create method. Set information about related agenda item
        into agenda_item_update_information container.
        """
        agenda_type = validated_data.pop('agenda_type', None)
        agenda_parent_id = validated_data.pop('agenda_parent_id', None)
        assignment = Assignment(**validated_data)
        assignment.agenda_item_update_information['type'] = agenda_type
        assignment.agenda_item_update_information[
            'parent_id'] = agenda_parent_id
        assignment.save()
        return assignment
Exemple #4
0
class AssignmentAllPollSerializer(ModelSerializer):
    """
    Serializer for assignment.models.AssignmentPoll objects.

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

    class Meta:
        model = AssignmentPoll
        fields = (
            'id',
            'yesnoabstain',
            'description',
            'published',
            'options',
            'votesvalid',
            'votesinvalid',
            'votescast',
            'votes',
            'has_votes',
            'assignment')  # js-data needs the assignment-id in the nested object to define relations.
        read_only_fields = ('yesnoabstain',)
        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 'yesnoabstain'=true poll with two candidates:

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

        Example data for a 'yesnoabstain'=false 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])

        # Update remaining writeable fields.
        instance.description = validated_data.get('description', instance.description)
        instance.published = validated_data.get('published', instance.published)
        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
Exemple #5
0
class MotionSerializer(ModelSerializer):
    """
    Serializer for motion.models.Motion objects.
    """
    active_version = PrimaryKeyRelatedField(read_only=True)
    log_messages = MotionLogSerializer(many=True, read_only=True)
    polls = MotionPollSerializer(many=True, read_only=True)
    reason = CharField(allow_blank=True, required=False, write_only=True)
    text = CharField(write_only=True)
    title = CharField(max_length=255, write_only=True)
    versions = MotionVersionSerializer(many=True, read_only=True)
    workflow_id = IntegerField(min_value=1,
                               required=False,
                               validators=[validate_workflow_field],
                               write_only=True)

    class Meta:
        model = Motion
        fields = (
            'id',
            'identifier',
            'title',
            'text',
            'reason',
            'versions',
            'active_version',
            'parent',
            'category',
            'submitters',
            'supporters',
            'state',
            'workflow_id',
            'tags',
            'attachments',
            'polls',
            'agenda_item_id',
            'log_messages',
        )
        read_only_fields = (
            'parent', 'state'
        )  # Some other fields are also read_only. See definitions above.

    @transaction.atomic
    def create(self, validated_data):
        """
        Customized method to create a new motion from some data.
        """
        motion = Motion()
        motion.title = validated_data['title']
        motion.text = validated_data['text']
        motion.reason = validated_data.get('reason', '')
        motion.identifier = validated_data.get('identifier')
        motion.category = validated_data.get('category')
        motion.reset_state(validated_data.get('workflow_id'))
        motion.save()
        if validated_data.get('submitters'):
            motion.submitters.add(*validated_data['submitters'])
        else:
            motion.submitters.add(validated_data['request_user'])
        motion.supporters.add(*validated_data.get('supporters', []))
        motion.attachments.add(*validated_data.get('attachments', []))
        motion.tags.add(*validated_data.get('tags', []))
        return motion

    @transaction.atomic
    def update(self, motion, validated_data):
        """
        Customized method to update a motion.
        """
        # Identifier and category.
        for key in ('identifier', 'category'):
            if key in validated_data.keys():
                setattr(motion, key, validated_data[key])

        # Workflow.
        workflow_id = validated_data.get('workflow_id')
        if workflow_id is not None and workflow_id != motion.workflow:
            motion.reset_state(workflow_id)

        # Decide if a new version is saved to the database.
        if (motion.state.versioning and
                not validated_data.get('disable_versioning', False)):  # TODO
            version = motion.get_new_version()
        else:
            version = motion.get_last_version()

        # Title, text, reason.
        for key in ('title', 'text', 'reason'):
            if key in validated_data.keys():
                setattr(version, key, validated_data[key])

        motion.save(use_version=version)

        # Submitters, supporters, attachments and tags
        for key in ('submitters', 'supporters', 'attachments', 'tags'):
            if key in validated_data.keys():
                attr = getattr(motion, key)
                attr.clear()
                attr.add(*validated_data[key])

        return motion
Exemple #6
0
class MotionPollSerializer(ModelSerializer):
    """
    Serializer for motion.models.MotionPoll objects.
    """
    yes = SerializerMethodField()
    no = SerializerMethodField()
    abstain = SerializerMethodField()
    votes = DictField(child=IntegerField(min_value=-2, allow_null=True),
                      write_only=True)
    has_votes = SerializerMethodField()

    class Meta:
        model = MotionPoll
        fields = ('id', 'motion', 'yes', 'no', 'abstain', 'votesvalid',
                  'votesinvalid', 'votescast', 'votes', 'has_votes')
        validators = (default_votes_validator, )

    def __init__(self, *args, **kwargs):
        # The following dictionary is just a cache for several votes.
        self._votes_dicts = {}
        return super().__init__(*args, **kwargs)

    def get_yes(self, obj):
        try:
            result = self.get_votes_dict(obj)['Yes']
        except KeyError:
            result = None
        return result

    def get_no(self, obj):
        try:
            result = self.get_votes_dict(obj)['No']
        except KeyError:
            result = None
        return result

    def get_abstain(self, obj):
        try:
            result = self.get_votes_dict(obj)['Abstain']
        except KeyError:
            result = None
        return result

    def get_votes_dict(self, obj):
        try:
            votes_dict = self._votes_dicts[obj.pk]
        except KeyError:
            votes_dict = self._votes_dicts[obj.pk] = {}
            for vote in obj.get_votes():
                votes_dict[vote.value] = vote.weight
        return votes_dict

    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:

            "votes": {"Yes": 10, "No": 4, "Abstain": -2}
        """
        # Update votes.
        votes = validated_data.get('votes')
        if votes:
            if len(votes) != 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.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(instance.get_options().get(),
                                                  votes)

        # Update remaining writeable fields.
        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
Exemple #7
0
class MotionSerializer(ModelSerializer):
    """
    Serializer for motion.models.Motion objects.
    """
    active_version = PrimaryKeyRelatedField(read_only=True)
    comments = MotionCommentsJSONSerializerField(required=False)
    log_messages = MotionLogSerializer(many=True, read_only=True)
    polls = MotionPollSerializer(many=True, read_only=True)
    reason = CharField(allow_blank=True, required=False, write_only=True)
    state_required_permission_to_see = SerializerMethodField()
    text = CharField(write_only=True)
    title = CharField(max_length=255, write_only=True)
    versions = MotionVersionSerializer(many=True, read_only=True)
    workflow_id = IntegerField(min_value=1,
                               required=False,
                               validators=[validate_workflow_field],
                               write_only=True)

    class Meta:
        model = Motion
        fields = (
            'id',
            'identifier',
            'title',
            'text',
            'reason',
            'versions',
            'active_version',
            'parent',
            'category',
            'motion_block',
            'origin',
            'submitters',
            'supporters',
            'comments',
            'state',
            'state_required_permission_to_see',
            'workflow_id',
            'recommendation',
            'tags',
            'attachments',
            'polls',
            'agenda_item_id',
            'log_messages',
        )
        read_only_fields = (
            'state',
            'recommendation',
        )  # Some other fields are also read_only. See definitions above.

    def validate(self, data):
        if 'text' in data:
            data['text'] = validate_html(data['text'])
        if 'reason' in data:
            data['reason'] = validate_html(data['reason'])
        validated_comments = []
        for comment in data.get('comments', []):
            validated_comments.append(validate_html(comment))
        data['comments'] = validated_comments
        return data

    @transaction.atomic
    def create(self, validated_data):
        """
        Customized method to create a new motion from some data.
        """
        motion = Motion()
        motion.title = validated_data['title']
        motion.text = validated_data['text']
        motion.reason = validated_data.get('reason', '')
        motion.identifier = validated_data.get('identifier')
        motion.category = validated_data.get('category')
        motion.motion_block = validated_data.get('motion_block')
        motion.origin = validated_data.get('origin', '')
        motion.comments = validated_data.get('comments')
        motion.parent = validated_data.get('parent')
        motion.reset_state(validated_data.get('workflow_id'))
        motion.save()
        if validated_data.get('submitters'):
            motion.submitters.add(*validated_data['submitters'])
        elif validated_data['request_user'].is_authenticated():
            motion.submitters.add(validated_data['request_user'])
        motion.supporters.add(*validated_data.get('supporters', []))
        motion.attachments.add(*validated_data.get('attachments', []))
        motion.tags.add(*validated_data.get('tags', []))
        return motion

    @transaction.atomic
    def update(self, motion, validated_data):
        """
        Customized method to update a motion.
        """
        # Identifier, category, motion_block, origin and comments.
        for key in ('identifier', 'category', 'motion_block', 'origin',
                    'comments'):
            if key in validated_data.keys():
                setattr(motion, key, validated_data[key])

        # Workflow.
        workflow_id = validated_data.get('workflow_id')
        if workflow_id is not None and workflow_id != motion.workflow:
            motion.reset_state(workflow_id)

        # Decide if a new version is saved to the database.
        if (motion.state.versioning and
                not validated_data.get('disable_versioning', False)):  # TODO
            version = motion.get_new_version()
        else:
            version = motion.get_last_version()

        # Title, text, reason.
        for key in ('title', 'text', 'reason'):
            if key in validated_data.keys():
                setattr(version, key, validated_data[key])

        motion.save(use_version=version)

        # Submitters, supporters, attachments and tags
        for key in ('submitters', 'supporters', 'attachments', 'tags'):
            if key in validated_data.keys():
                attr = getattr(motion, key)
                attr.clear()
                attr.add(*validated_data[key])

        return motion

    def get_state_required_permission_to_see(self, motion):
        """
        Returns the permission (as string) that is required for non
        managers that are not submitters to see this motion in this state.

        Hint: Most states have and empty string here so this restriction is
        disabled.
        """
        return motion.state.required_permission_to_see
Exemple #8
0
class AssignmentSerializer(ModelSerializer):
    """
    Serializer for assignment.models.Assignment objects. With all polls.
    """

    assignment_related_users = AssignmentRelatedUserSerializer(many=True,
                                                               read_only=True)
    agenda_create = BooleanField(write_only=True,
                                 required=False,
                                 allow_null=True)
    agenda_type = IntegerField(write_only=True,
                               required=False,
                               min_value=1,
                               max_value=3,
                               allow_null=True)
    agenda_parent_id = IntegerField(write_only=True,
                                    required=False,
                                    min_value=1)
    polls = IdPrimaryKeyRelatedField(many=True, read_only=True)

    class Meta:
        model = Assignment
        fields = (
            "id",
            "title",
            "description",
            "open_posts",
            "phase",
            "assignment_related_users",
            "default_poll_description",
            "agenda_item_id",
            "list_of_speakers_id",
            "agenda_create",
            "agenda_type",
            "agenda_parent_id",
            "tags",
            "attachments",
            "number_poll_candidates",
            "polls",
        )
        validators = (posts_validator, )

    def validate(self, data):
        if "description" in data:
            data["description"] = validate_html_strict(data["description"])
        return data

    def create(self, validated_data):
        """
        Customized create method. Set information about related agenda item
        into agenda_item_update_information container.
        """
        tags = validated_data.pop("tags", [])
        attachments = validated_data.pop("attachments", [])
        request_user = validated_data.pop(
            "request_user")  # this should always be there
        agenda_create = validated_data.pop("agenda_create", None)
        agenda_type = validated_data.pop("agenda_type", None)
        agenda_parent_id = validated_data.pop("agenda_parent_id", None)

        assignment = Assignment(**validated_data)
        if has_perm(request_user, "agenda.can_manage"):
            assignment.agenda_item_update_information["create"] = agenda_create
            assignment.agenda_item_update_information["type"] = agenda_type
            assignment.agenda_item_update_information[
                "parent_id"] = agenda_parent_id

        assignment.save()
        assignment.tags.add(*tags)
        assignment.attachments.add(*attachments)
        inform_changed_data(assignment)
        return assignment