Esempio n. 1
0
class ProjectSerializer(serializers.ModelSerializer):
    resource_uri = serializers.SerializerMethodField()
    created = TimezoneAwareDateTimeField(read_only=True)
    modified = TimezoneAwareDateTimeField(read_only=True)

    class Meta:
        model = Project
        fields = ('name', 'slug', 'description', 'guidelines', 'modified',
                  'created', 'workflow_enabled', 'resource_uri')
        # Based on the model code, slug can be blank, but this seems bad to
        # allow for API requests
        read_only_fields = ('modified', 'created')
        extra_kwargs = {
            'slug': {
                'required': True
            },
        }

    def get_resource_uri(self, project):
        return reverse('api:projects-detail',
                       kwargs={
                           'team_slug': self.context['team'].slug,
                           'slug': project.slug,
                       },
                       request=self.context['request'])

    def create(self, validated_data):
        return Project.objects.create(team=self.context['team'],
                                      **validated_data)
Esempio n. 2
0
class TaskSerializer(serializers.ModelSerializer):
    resource_uri = serializers.SerializerMethodField()
    video_id = TeamVideoField(source='team_video')
    assignee = TeamMemberField(required=False)
    type = MappedChoiceField(Task.TYPE_CHOICES)
    created = TimezoneAwareDateTimeField(read_only=True)
    modified = TimezoneAwareDateTimeField(read_only=True)
    completed = TimezoneAwareDateTimeField(read_only=True)
    approved = MappedChoiceField(
        Task.APPROVED_CHOICES, required=False,
        default=Task._meta.get_field('approved').get_default(),
    )

    class Meta:
        model = Task
        fields = (
            'id', 'video_id', 'language', 'type', 'assignee', 'priority',
            'created', 'modified', 'completed', 'approved', 'resource_uri',
        )

    def get_resource_uri(self, task):
        return reverse('api:tasks-detail', kwargs={
            'team_slug': self.context['team'].slug,
            'id': task.id,
        }, request=self.context['request'])

    def create(self, validated_data):
        validated_data['team'] = self.context['team']
        return super(TaskSerializer, self).create(validated_data)
Esempio n. 3
0
class ApplicationSerializer(serializers.ModelSerializer):
    user = UserField(read_only=True)
    status = MappedChoiceField(
        Application.STATUSES,
        default=Application._meta.get_field('status').get_default())
    resource_uri = serializers.SerializerMethodField()
    created = TimezoneAwareDateTimeField(read_only=True)
    modified = TimezoneAwareDateTimeField(read_only=True)

    default_error_messages = {
        'invalid-status-choice': "Unknown status: {status}",
        'not-pending': "Application not pending",
    }

    def get_resource_uri(self, application):
        return reverse('api:team-application-detail',
                       kwargs={
                           'team_slug': self.context['team'].slug,
                           'id': application.id,
                       },
                       request=self.context['request'])

    class Meta:
        model = Application
        fields = (
            'id',
            'status',
            'user',
            'note',
            'created',
            'modified',
            'resource_uri',
        )
        read_only_fields = (
            'id',
            'note',
            'created',
            'modified',
        )

    def validate_status(self, status):
        if status not in (Application.STATUS_APPROVED,
                          Application.STATUS_DENIED):
            self.fail('invalid-status-choice', status=status)
        return status

    def update(self, instance, validated_data):
        if instance.status != Application.STATUS_PENDING:
            self.fail('not-pending')

        if validated_data['status'] == Application.STATUS_APPROVED:
            instance.approve(self.context['user'], 'API')
        elif validated_data['status'] == Application.STATUS_DENIED:
            instance.deny(self.context['user'], 'API')
        return instance
Esempio n. 4
0
class ActivitySerializer(serializers.ModelSerializer):
    type = serializers.IntegerField(source='action_type')
    user = serializers.CharField(source='user.username')
    comment = serializers.CharField(source='comment.content')
    created = TimezoneAwareDateTimeField(read_only=True)
    video = serializers.CharField(source='video.video_id')
    video_uri = serializers.HyperlinkedRelatedField(
        source='video',
        view_name='api:video-detail',
        lookup_field='video_id',
        read_only=True)
    language = serializers.CharField(source='new_language.language_code')
    language_url = serializers.SerializerMethodField()
    resource_uri = serializers.HyperlinkedIdentityField(
        view_name='api:activity-detail',
        lookup_field='id',
    )

    def get_language_url(self, action):
        if not action.new_language:
            return None
        return reverse('api:subtitle-language-detail',
                       kwargs={
                           'video_id': action.new_language.video.video_id,
                           'language_code': action.new_language.language_code,
                       },
                       request=self.context['request'])

    class Meta:
        model = Action
        fields = ('id', 'type', 'created', 'video', 'video_uri', 'language',
                  'language_url', 'user', 'comment', 'new_video_title',
                  'resource_uri')
Esempio n. 5
0
class TeamNotificationSerializer(serializers.ModelSerializer):
    in_progress = serializers.BooleanField(source='is_in_progress')
    timestamp = TimezoneAwareDateTimeField(read_only=True)
    data = serializers.SerializerMethodField()
    resource_uri = serializers.SerializerMethodField()

    class Meta:
        model = TeamNotification
        fields = ('number', 'url', 'data', 'timestamp', 'in_progress',
                  'response_status', 'error_message', 'resource_uri')

    def get_data(self, notification):
        try:
            return json.loads(notification.data)
        except StandardError:
            # Error parsing the JSON.   Just return data as a string
            return notification.data

    def get_resource_uri(self, notification):
        return reverse('api:team-notifications-detail',
                       kwargs={
                           'team_slug': self.context['team'].slug,
                           'number': notification.number,
                       },
                       request=self.context['request'])
Esempio n. 6
0
class NotesSerializer(serializers.Serializer):
    user = serializers.CharField(source='user.username', read_only=True)
    created = TimezoneAwareDateTimeField(read_only=True)
    body = serializers.CharField()

    def create(self, validated_data):
        return self.context['editor_notes'].post(
            self.context['user'], validated_data['body'])
Esempio n. 7
0
class NotesSerializer(serializers.Serializer):
    user = UserField(read_only=True)
    created = TimezoneAwareDateTimeField(read_only=True)
    body = serializers.CharField()

    def create(self, validated_data):
        if self.context['editor_notes'] is None:
            raise PermissionDenied()
        return self.context['editor_notes'].post(self.context['user'],
                                                 validated_data['body'])
Esempio n. 8
0
class LegacyActivitySerializer(serializers.ModelSerializer):
    type = serializers.IntegerField(source='type_code')
    type_name = serializers.SlugField(source='type')
    user = serializers.CharField(source='user.username')
    comment = serializers.SerializerMethodField()
    new_video_title = serializers.SerializerMethodField()
    created = TimezoneAwareDateTimeField(read_only=True)
    video = serializers.CharField(source='video.video_id')
    video_uri = serializers.HyperlinkedRelatedField(
        source='video',
        view_name='api:video-detail',
        lookup_field='video_id',
        read_only=True)
    language = serializers.SerializerMethodField()
    language_url = serializers.SerializerMethodField()
    resource_uri = serializers.HyperlinkedIdentityField(
        view_name='api:activity-detail',
        lookup_field='id',
    )

    def get_language(self, record):
        return record.language_code or None

    def get_comment(self, record):
        if record.type == 'comment-added':
            return record.get_related_obj().content
        else:
            return None

    def get_new_video_title(self, record):
        if record.type == 'video-title-changed':
            return record.get_related_obj().new_title
        else:
            return None

    def get_language_url(self, record):
        if not (record.language_code and record.video):
            return None
        return reverse('api:subtitle-language-detail',
                       kwargs={
                           'video_id': record.video.video_id,
                           'language_code': record.language_code,
                       },
                       request=self.context['request'])

    class Meta:
        model = ActivityRecord
        fields = ('id', 'type', 'type_name', 'created', 'video', 'video_uri',
                  'language', 'language_url', 'user', 'comment',
                  'new_video_title', 'resource_uri')
Esempio n. 9
0
class VideoURLSerializer(serializers.Serializer):
    created = TimezoneAwareDateTimeField(read_only=True)
    url = serializers.URLField(max_length=URL_MAX_LENGTH)
    primary = serializers.BooleanField(required=False)
    original = serializers.BooleanField(required=False)
    id = serializers.IntegerField(read_only=True)
    resource_uri = serializers.SerializerMethodField()
    videoid = serializers.CharField(read_only=True)
    type = serializers.SerializerMethodField(read_only=True)

    def get_resource_uri(self, video_url):
        return reverse('api:video-url-detail',
                       kwargs={
                           'video_id': self.context['video'].video_id,
                           'pk': video_url.id,
                       },
                       request=self.context['request'])

    def get_type(self, video_url):
        vt = video_type_registrar[video_url.type]
        return vt.name

    def create(self, validated_data):
        try:
            new_url = self.context['video'].add_url(validated_data['url'],
                                                    self.context['user'])
        except Video.DuplicateUrlError as e:
            raise serializers.ValidationError(
                "DuplicateUrlError for url: {}".format(e.video_url))

        if validated_data.get('primary'):
            new_url.make_primary(self.context['user'])

        if ('original' in validated_data
                and validated_data['original'] != new_url.original):
            new_url.original = validated_data['original']
            new_url.save()

        return new_url

    def update(self, video_url, validated_data):
        if ('original' in validated_data
                and validated_data['original'] != video_url.original):
            video_url.original = validated_data['original']
            video_url.save()

        if validated_data.get('primary'):
            video_url.make_primary(self.context['user'])

        return video_url
Esempio n. 10
0
class TeamNotificationSerializer(serializers.ModelSerializer):
    in_progress = serializers.BooleanField(source='is_in_progress')
    timestamp = TimezoneAwareDateTimeField(read_only=True)
    data = serializers.SerializerMethodField()

    class Meta:
        model = TeamNotification
        fields = ('number', 'url', 'data', 'timestamp', 'in_progress',
                  'response_status', 'error_message')

    def get_data(self, notification):
        try:
            return json.loads(notification.data)
        except StandardError:
            # Error parsing the JSON.   Just return data as a string
            return notification.data
Esempio n. 11
0
class VideoURLSerializer(serializers.Serializer):
    created = TimezoneAwareDateTimeField(read_only=True)
    url = serializers.CharField()
    primary = serializers.BooleanField(required=False)
    original = serializers.BooleanField(required=False)
    id = serializers.IntegerField(read_only=True)
    resource_uri = serializers.SerializerMethodField()
    videoid = serializers.CharField(read_only=True)
    type = serializers.SerializerMethodField(read_only=True)

    def get_resource_uri(self, video_url):
        return reverse('api:video-url-detail', kwargs={
            'video_id': self.context['video'].video_id,
            'pk': video_url.id,
        }, request=self.context['request'])

    def get_type(self, video_url):
        vt = video_type_registrar[video_url.type]
        return vt.name

    def create(self, validated_data):
        vt = video_type_registrar.video_type_for_url(validated_data['url'])

        new_url = self.context['video'].videourl_set.create(
            url=validated_data['url'],
            original=validated_data.get('original', False),
            type=vt.abbreviation,
            added_by=self.context['user'],
        )
        if validated_data.get('primary'):
            new_url.make_primary(self.context['user'])
        return new_url

    def update(self, video_url, validated_data):
        if ('original' in validated_data and
            validated_data['original'] != video_url.original):
            video_url.original = validated_data['original']
            video_url.save()

        if validated_data.get('primary'):
            video_url.make_primary(self.context['user'])

        return video_url
Esempio n. 12
0
class VideoSerializer(serializers.Serializer):
    # Note we could try to use ModelSerializer, but we are so far from the
    # default implementation that it makes more sense to not inherit.
    id = serializers.CharField(source='video_id', read_only=True)
    video_url = serializers.URLField(write_only=True, required=True)
    video_type = serializers.SerializerMethodField()
    primary_audio_language_code = LanguageCodeField(required=False,
                                                    allow_blank=True)
    original_language = serializers.CharField(source='language',
                                              read_only=True)
    title = serializers.CharField(required=False, allow_blank=True)
    description = serializers.CharField(required=False, allow_blank=True)
    duration = serializers.IntegerField(required=False)
    thumbnail = serializers.URLField(required=False, allow_blank=True)
    created = TimezoneAwareDateTimeField(read_only=True)
    team = TeamSerializer(required=False, allow_null=True)
    project = ProjectSerializer(required=False, allow_null=True)
    all_urls = serializers.SerializerMethodField()
    metadata = VideoMetadataSerializer(required=False)
    languages = VideoLanguageShortSerializer(source='all_subtitle_languages',
                                             many=True,
                                             read_only=True)
    activity_uri = serializers.HyperlinkedIdentityField(
        view_name='api:video-activity',
        lookup_field='video_id',
    )
    urls_uri = serializers.HyperlinkedIdentityField(
        view_name='api:video-url-list',
        lookup_field='video_id',
    )
    subtitle_languages_uri = serializers.HyperlinkedIdentityField(
        view_name='api:subtitle-language-list',
        lookup_field='video_id',
    )
    resource_uri = serializers.HyperlinkedIdentityField(
        view_name='api:video-detail', lookup_field='video_id')

    default_error_messages = {
        'project-without-team': "Can't specify project without team",
        'unknown-project': 'Unknown project: {project}',
        'video-exists': 'Video already exists for {url}',
        'invalid-url': 'Invalid URL: {url}',
    }

    class Meta:
        list_serializer_class = VideoListSerializer

    def __init__(self, *args, **kwargs):
        super(VideoSerializer, self).__init__(*args, **kwargs)
        if self.instance:
            # video_url should only be sent for creation
            self.fields['video_url'].read_only = True

    @property
    def team_video(self):
        if self.instance:
            return self.instance.get_team_video()
        else:
            return None

    def get_all_urls(self, video):
        video_urls = list(video.get_video_urls())
        video_urls.sort(key=lambda vurl: vurl.primary, reverse=True)
        return [vurl.url for vurl in video_urls]

    def get_video_type(self, video):
        types = set()
        for url in video.get_video_urls():
            types.add(url.type)
        if len(types) == 1:
            return types.pop()
        return ""

    def will_add_video_to_team(self):
        if not self.team_video:
            return 'team' in self.validated_data
        if 'team' in self.validated_data:
            if self.validated_data['team'] != self.team_video.team:
                return True
            if 'project' in self.validated_data:
                if self.validated_data['project'] != self.team_video.project:
                    return True
        return False

    def will_remove_video_from_team(self):
        if 'team' not in self.validated_data or not self.team_video:
            return False
        return self.team_video.team != self.validated_data['team']

    def to_internal_value(self, data):
        self.fixup_data(data)
        return super(VideoSerializer, self).to_internal_value(data)

    def validate(self, data):
        if data.get('project'):
            if not data.get('team'):
                self.fail('project-without-team')
            try:
                data['project'] = Project.objects.get(team=data['team'],
                                                      slug=data['project'])
            except Project.DoesNotExist:
                self.fail('unknown-project', project=data['project'])
        return data

    def fixup_data(self, data):
        """Alter incoming data to support deprecated behavior."""
        for name, value in data.items():
            if value == '':
                # Remove any field has the empty string as its value
                # This is deprecated behavior form the old API.
                del data[name]
            elif name in ('team', 'project') and value == 'null':
                # Replace "null" with None for team/project
                data[name] = None

    def to_representation(self, video):
        data = super(VideoSerializer, self).to_representation(video)
        # convert blank language codes to None
        if video.primary_audio_language_code == '':
            data['primary_audio_language_code'] = None
            data['original_language'] = None
        return data

    def create(self, validated_data):
        def setup_video(video, video_url):
            for key in ('title', 'description', 'duration', 'thumbnail',
                        'primary_audio_language_code'):
                if validated_data.get(key):
                    setattr(video, key, validated_data[key])
            if validated_data.get('metadata'):
                video.update_metadata(validated_data['metadata'], commit=False)
            self._update_team(video, validated_data)

        try:
            return Video.add(validated_data['video_url'], self.context['user'],
                             setup_video)[0]
        except VideoTypeError:
            self.fail('invalid-url', url=validated_data['video_url'])
        except Video.UrlAlreadyAdded:
            self.fail('video-exists', url=validated_data['video_url'])

    def update(self, video, validated_data):
        simple_fields = (
            'title',
            'description',
            'duration',
            'thumbnail',
            'primary_audio_language_code',
        )
        for field_name in simple_fields:
            if field_name in validated_data:
                if field_name == "duration":
                    if not getattr(video, field_name):
                        setattr(video, field_name, validated_data[field_name])
                else:
                    setattr(video, field_name, validated_data[field_name])
        if validated_data.get('metadata'):
            video.update_metadata(validated_data['metadata'], commit=True)
        self._update_team(video, validated_data)
        video.save()
        return video

    def _update_team(self, video, validated_data):
        if 'team' not in validated_data:
            return
        team = validated_data['team']
        project = validated_data.get('project')
        team_video = video.get_team_video()
        if team is None:
            if team_video:
                team_video.delete()
            video.is_public = True
        else:
            if project is None:
                project = team.default_project
            if team_video:
                team_video.move_to(team, project, self.context['user'])
            else:
                TeamVideo.objects.create(video=video,
                                         team=team,
                                         project=project,
                                         added_by=self.context['user'])
                video.is_public = team.is_visible

        video.clear_team_video_cache()
Esempio n. 13
0
class ActivitySerializer(serializers.ModelSerializer):
    type = serializers.SlugField()
    user = UserField(read_only=True)
    date = TimezoneAwareDateTimeField(source='created')
    video = serializers.CharField(source='video.video_id')
    language = serializers.SerializerMethodField()
    video_uri = serializers.HyperlinkedRelatedField(
        source='video',
        view_name='api:video-detail',
        lookup_field='video_id',
        read_only=True)
    language_uri = serializers.SerializerMethodField()

    def get_language(self, record):
        return record.language_code or None

    def get_language_uri(self, record):
        if not (record.language_code and record.video):
            return None
        return reverse('api:subtitle-language-detail',
                       kwargs={
                           'video_id': record.video.video_id,
                           'language_code': record.language_code,
                       },
                       request=self.context['request'])

    def to_representation(self, record):
        data = super(ActivitySerializer, self).to_representation(record)
        extra_data_method_name = 'get_{}_extra'.format(
            record.type.replace('-', '_'))
        extra_field_method = getattr(self, extra_data_method_name, None)
        if extra_field_method:
            data.update(extra_field_method(record))
        return data

    def get_video_url_added_extra(self, record):
        url_edit = record.get_related_obj()
        return {
            'url': url_edit.new_url,
        }

    def get_video_url_edited_extra(self, record):
        url_edit = record.get_related_obj()
        return {
            'old_url': url_edit.old_url,
            'new_url': url_edit.new_url,
        }

    def get_video_url_deleted_extra(self, record):
        url_edit = record.get_related_obj()
        return {
            'url': url_edit.old_url,
        }

    def get_video_deleted_extra(self, record):
        video_deletion = record.get_related_obj()
        return {
            'title': video_deletion.title,
        }

    class Meta:
        model = ActivityRecord
        fields = (
            'type',
            'date',
            'user',
            'video',
            'language',
            'video_uri',
            'language_uri',
        )
Esempio n. 14
0
class SubtitleLanguageSerializer(serializers.Serializer):
    id = serializers.IntegerField(read_only=True)
    created = TimezoneAwareDateTimeField(read_only=True)
    language_code = LanguageCodeField()
    is_primary_audio_language = serializers.BooleanField(required=False)
    is_rtl = serializers.BooleanField(read_only=True)
    is_translation = serializers.SerializerMethodField()
    original_language_code = serializers.SerializerMethodField()
    name = serializers.CharField(source='get_language_code_display',
                                 read_only=True)
    title = serializers.CharField(source='get_title', read_only=True)
    description = serializers.CharField(source='get_description',
                                        read_only=True)
    metadata = VideoMetadataSerializer(required=False, read_only=True)
    subtitle_count = serializers.IntegerField(read_only=True,
                                              source='get_subtitle_count')
    subtitles_complete = serializers.BooleanField(required=False)
    versions = MiniSubtitleVersionsField(read_only=True)
    resource_uri = serializers.SerializerMethodField()

    default_error_messages = {
        'language-exists': _('Language already created: {language_code}'),
    }

    class Meta:
        list_serializer_class = SubtitleLanguageListSerializer

    def __init__(self, *args, **kwargs):
        super(SubtitleLanguageSerializer, self).__init__(*args, **kwargs)
        if self.instance:
            self.fields['language_code'].read_only = True

    def get_is_translation(self, language):
        return compat.subtitlelanguage_is_translation(language)

    def get_original_language_code(self, language):
        return compat.subtitlelanguage_original_language_code(language)

    def get_resource_uri(self, language):
        kwargs = {
            'video_id': language.video.video_id,
            'language_code': language.language_code,
        }
        return reverse('api:subtitle-language-detail', kwargs=kwargs,
                       request=self.context['request'])

    def to_representation(self, language):
        if 'versions' not in self.context:
            # For the list view, the SubtitleLanguageListSerializer generates
            # versions, for the detail view we need to generate versions
            # ourselves
            _fetch_versions([language], self.context)
        data = super(SubtitleLanguageSerializer, self).to_representation(
            language)
        data['num_versions'] = len(data['versions'])
        data['is_original'] = data['is_primary_audio_language']
        self.add_reviewer_and_approver(data, language)
        return data

    def add_reviewer_and_approver(self, data, language):
        """Add the reviewer/approver fields."""
        for version in self.context['versions'][language.id]:
            reviewer = version.get_reviewed_by()
            approver = version.get_approved_by()
            if reviewer:
                data['reviewer'] = reviewer.username
            if approver:
                data['approver'] = approver.username

    def validate_language_code(self, language_code):
        if (SubtitleLanguage.objects
            .filter(video=self.context['video'],
                    language_code=language_code)
            .exists()):
            raise serializers.ValidationError("Language already exists")
        return language_code

    def create(self, validated_data):
        language = SubtitleLanguage.objects.create(
            video=self.context['video'],
            language_code=validated_data['language_code'])
        return self.update(language, validated_data)

    def update(self, language, validated_data):
        subtitles_complete = validated_data.get(
            'subtitles_complete',
            self.initial_data.get('is_complete', None))
        primary_audio_language = validated_data.get(
            'is_primary_audio_language',
            self.initial_data.get('is_original', None))

        video = self.context['video']
        if subtitles_complete is not None:
            language.subtitles_complete = subtitles_complete
            try:
                language.save()
            except IntegrityError:
                self.fail('language-exists',
                          language_code=language.language_code)
        if primary_audio_language is not None:
            video.primary_audio_language_code = language.language_code
            video.save()
        videos.tasks.video_changed_tasks.delay(video.pk)
        return language