Пример #1
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
Пример #2
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()
Пример #3
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)
    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 = serializers.DateTimeField(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)
    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 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):
        data = self.fixup_data(data)
        data = super(VideoSerializer, self).to_internal_value(data)
        # we have to wait until now because we can't fetch the project until
        # we know the team
        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."""
        # iterate over data to build a new dictionary.  This is required
        # because data is a MergeDict, which has issues with deletion.
        new_data = {}
        for name, value in data.items():
            # Remove any field has the empty string as its value
            # This is deprecated behavior form the old API.
            if value == '':
                continue
            # Replace "null" with None for team/project
            if name in ('team', 'project') and value == 'null':
                value = None
            new_data[name] = value
        return new_data

    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):
        set_values = {}
        for key in ('title', 'description', 'duration', 'thumbnail',
                    'primary_audio_language_code', 'metadata'):
            if key in validated_data:
                set_values[key] = validated_data[key]
        video, created = Video.get_or_create_for_url(
            validated_data['video_url'],
            user=self.context['user'],
            set_values=set_values,
        )
        if video is None:
            self.fail('invalid-url', url=validated_data['video_url'])
        if not created:
            self.fail('video-exists', url=validated_data['video_url'])
        self._update_team(video, validated_data)
        return video

    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:
                setattr(video, field_name, validated_data[field_name])
        if validated_data.get('metadata'):
            video.update_metadata(validated_data['metadata'], commit=True)
        else:
            video.save()
        self._update_team(video, validated_data)
        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()
        else:
            if project is None:
                project = team.default_project
            if team_video:
                team_video.move_to(team, project)
            else:
                TeamVideo.objects.create(video=video,
                                         team=team,
                                         project=project)
        video.clear_team_video_cache()