src/notes/api/serializers/core.py
author ymh <ymh.work@gmail.com>
Wed, 18 Jul 2018 17:32:09 +0200
changeset 142 56850f5c73f6
parent 133 6f3078f7fd47
permissions -rw-r--r--
- upgrade libraries - python 3.7 compatibility - First protocol management implementation

"""
Serializers for model core classes
"""
import logging

from django.contrib.auth.models import Group
from django.db import transaction
from notes.api.fields.category import ProtocolField
from notes import constants
from notes.models import Note, Session
from protocols.models import Protocol
from rest_framework import serializers

logger = logging.getLogger(__name__)


class DetailNoteSerializer(serializers.ModelSerializer):
    class Meta:
        model = Note
        fields = (
            'ext_id', 'version', 'created', 'updated',
            'plain', 'html', 'raw',
            'categorization', 'margin_note', 'tc_start', 'tc_end'
        )
        read_only_fields = ('ext_id', 'version', 'created', 'updated')

class UpdateNoteSerializer(serializers.ModelSerializer):
    class Meta:
        model = Note
        fields = (
            'ext_id', 'version', 'created', 'updated',
            'plain', 'html', 'raw',
            'categorization', 'margin_note', 'tc_start', 'tc_end'
        )
        read_only_fields = ('ext_id', 'version', 'created', 'updated', 'tc_start', 'tc_end')

class CreateNoteSerializer(serializers.ModelSerializer):
    class Meta:
        model = Note
        fields = (
            'ext_id', 'version', 'created', 'updated',
            'plain', 'html', 'raw',
            'categorization', 'margin_note', 'tc_start', 'tc_end'
        )
        read_only_fields = ('version', 'created', 'updated')

    def to_internal_value(self, data):
        super_data = super().to_internal_value(data)
        super_data['session'] = Session.objects.get(
            ext_id=self.context['view'].kwargs['session_ext_id']
        )
        return super_data

class ListNoteSerializer(serializers.ModelSerializer):
    class Meta:
        model = Note
        fields = (
            'ext_id', 'tc_start', 'tc_end'
        )
        read_only_fields = ('ext_id', )

class RootListNoteSerializer(serializers.ModelSerializer):
    session = serializers.SlugRelatedField(read_only=True, slug_field='ext_id')

    class Meta:
        model = Note
        fields = (
            'ext_id', 'tc_start', 'tc_end', 'session'
        )
        read_only_fields = ('ext_id', )

class RootDetailNoteSerializer(serializers.ModelSerializer):
    session = serializers.SlugRelatedField(read_only=True, slug_field='ext_id')

    class Meta:
        model = Note
        fields = (
            'ext_id', 'version', 'created', 'updated',
            'plain', 'html', 'raw',
            'categorization', 'margin_note', 'tc_start', 'tc_end',
            'session'
        )
        read_only_fields = (
            'ext_id', 'version', 'created', 'updated',
            'plain', 'html', 'raw',
            'categorization', 'margin_note', 'tc_start', 'tc_end',
            'session'
        )


class ListSessionSerializer(serializers.ModelSerializer):

    owner = serializers.SlugRelatedField(
        read_only=True, slug_field='username', default=serializers.CurrentUserDefault())
    group = serializers.SlugRelatedField(read_only=True, slug_field='name')
    protocol = ProtocolField(required=False, read_only=True)

    class Meta:
        model = Session
        fields = (
            'ext_id', 'version', 'date', 'created', 'updated',
            'owner', 'title', 'description', 'protocol', 'group'
        )
        read_only_fields = ('ext_id', 'version', 'created', 'updated', 'owner', 'group', 'protocol')


class DetailSessionSerializer(serializers.ModelSerializer):

    owner = serializers.SlugRelatedField(read_only=True, slug_field='username')
    notes = DetailNoteSerializer(many=True, read_only=True)
    group = serializers.SlugRelatedField(slug_field='name', read_only=True)
    protocol = ProtocolField(required=False, read_only=True)

    class Meta:
        model = Session
        fields = (
            'ext_id', 'version', 'date', 'created', 'updated',
            'owner', 'title', 'description', 'protocol', 'group',
            'notes'
        )
        read_only_fields = ('ext_id', 'version', 'created', 'updated', 'owner', 'group', 'protocol')

class BaseSessionSerializer(serializers.ModelSerializer):

    owner = serializers.SlugRelatedField(
        read_only=True, slug_field='username', default=serializers.CurrentUserDefault())
    group = serializers.SlugRelatedField(slug_field='name', queryset=Group.objects.all(), required=False, allow_null=True)

    @transaction.atomic()
    def save(self,**kwargs):
        return super().save(**kwargs)

    def create(self, validated_data):
        return super().create(validated_data)

    def update(self, instance, validated_data):
        return super().update(instance, validated_data)

    def validate(self, data):
        data = super().validate(data)

        group = data.get('group')
        owner = data.get('owner')

        if owner is None:
            owner = self.fields['owner'].get_default()

        if group is None:
            if owner.profile and owner.profile.default_group:
                group = owner.profile.default_group
            if group is None and owner:
                group = Group.objects.filter(profile__owner_personal=owner).first()

        if group is None:
            raise serializers.ValidationError("group field is required or default group or personal group could not be found for owner")
        elif not owner in group.user_set.all():
            raise serializers.ValidationError("Owner must be in group")

        # Be careful: we update the data in the "validate". This is a side effect.
        data['group'] = group
        data['owner'] = owner

        protocol = data.get('protocol')
        if protocol is None:
            data['protocol'] = group.profile.protocol
        elif isinstance(protocol, dict) and 'owner' not in protocol:
            data['protocol']['owner'] = group.name

        return data

class UpdateSessionSerializer(BaseSessionSerializer):

    protocol = ProtocolField(required=False, allow_null=True, read_only=True)

    class Meta:
        model = Session
        fields = (
            'ext_id', 'version', 'date', 'created', 'updated',
            'owner', 'title', 'description', 'protocol', 'group'
        )
        read_only_fields = ('ext_id', 'protocol', 'version', 'created', 'updated', 'owner')

    @transaction.atomic()
    def save(self,**kwargs):
        return super().save(**kwargs)

class CreateSessionSerializer(BaseSessionSerializer):

    protocol = ProtocolField(required=False, allow_null=True)

    class Meta:
        model = Session
        fields = (
            'ext_id', 'version', 'date', 'created', 'updated',
            'owner', 'title', 'description', 'protocol', 'group'
        )
        read_only_fields = ('version', 'created', 'updated', 'owner')

    @transaction.atomic()
    def save(self,**kwargs):
        return super().save(**kwargs)

    def create(self, validated_data):
        protocol = validated_data.pop('protocol')

        if protocol is None or isinstance(protocol, dict):

            protocol_revision = Protocol.objects.create_new_revision(protocol.get('id'), protocol, None)
            validated_data['protocol'] = "%s%s.%s" % (constants.PROTOCOL_URN_PREFIX, protocol_revision.protocol.ext_id, protocol_revision.version)

        elif isinstance(protocol, str) and protocol.startswith(constants.PROTOCOL_URN_PREFIX):
            validated_data['protocol'] = protocol
        else:
            raise Exception("Bad format for protocol")

        return super().create(validated_data)