Esempio n. 1
0
class WebUpdate(ArchiveModel, models.Model):
    """
    Minor updates.
    """
    id = archive_fields.IdField()
    title = archive_fields.TitleField()
    link = archive_fields.URLField(blank=True)
    description = archive_fields.DescriptionField(blank=True)
    type = models.ForeignKey(WebUpdateType)

    class Archive:
        class Meta:
            root = archive_settings.WEBUPDATE_ROOT
            release_date = True
            embargo_date = False
            last_modified = True
            created = True
            published = True
            sort_fields = [
                'release_date',
            ]
            rename_pk = ('announcements_webupdate', 'id')

    class Meta:
        ordering = ['-release_date']

    def get_absolute_url(self):
        return self.link

    def __unicode__(self):
        return "%s: %s" % (self.id, self.title)
Esempio n. 2
0
class StandardArchiveInfo(models.Model):
    """
    Abstract model containing fields shared across all archives
    """
    def __init__(self, *args, **kwargs):
        super(StandardArchiveInfo, self).__init__(*args, **kwargs)
        # If credit is not set, the set default credit in object.
        if not self.credit:
            self.credit = DEFAULT_CREDIT

    id = archivesfields.IdField()
    title = archivesfields.TitleField()
    description = archivesfields.DescriptionField()
    priority = archivesfields.PriorityField(default=0)
    credit = metadatafields.AVMCreditField(default=DEFAULT_CREDIT_FUNC)

    # Add the possibility to choose categories
    archive_category = models.ManyToManyField(ArchiveCategory, blank=True)

    class Meta:
        abstract = True
        ordering = [
            '-priority',
            '-id',
        ]

    class Archive:
        """
        All product archives will inherit these resources.
        """
        original = ImageResourceManager(type=types.OriginalImageType)
        large = ImageResourceManager(derived='original',
                                     type=types.LargeJpegType)
        medium = ImageResourceManager(derived='original',
                                      type=types.MediumJpegType)
        screen = ImageResourceManager(derived='original',
                                      type=types.ScreensizeJpegType)
        thumb = ImageResourceManager(derived='original',
                                     type=types.ThumbnailJpegType)

        class Meta:
            release_date = True
            embargo_date = True
            last_modified = True
            created = True
            published = True
            sort_fields = [
                'last_modified',
                'release_date',
                'priority',
            ]

    def __unicode__(self):
        """
        Default is to return the id as name.
        """
        return self.id
Esempio n. 3
0
class VideoScript( ArchiveModel, models.Model ):
    """
    Model for storing scripts for videos.
    """
    id = archive_fields.IdField()
    video = TranslationForeignKey(Video)
    lang = models.CharField(verbose_name=_('Language'), max_length=7, choices=SUBTITLE_LANGUAGES, default=settings.LANGUAGE_CODE, db_index=True)
    # type = models.CharField(verbose_name=_('Audio track type'), max_length=25, choices=SPLIT_AUDIO_TYPES)

    def save( self, **kwargs ):
        """
        Override save() to always set id as video_id + '_' + lang

        # TODO: check video renaming
        """
        old_id = self.id
        self.id = '%s_%s' % (self.video.id, self.lang)

        if old_id != self.id:  # delete old
            try:
                old = VideoScript.objects.get( id=old_id )
                old.delete()
            except VideoScript.DoesNotExist:
                pass

        super( VideoScript, self ).save( **kwargs )

    def __unicode__( self ):
        return dict( SUBTITLE_LANGUAGES ).get( self.lang, self.lang )

    class Meta:
        verbose_name = _(u'Video Script')
        app_label = 'media'

    class Archive:
        script = ResourceManager( type=types.PDFType, verbose_name=_( u"Broadcast Audio Track" ) )

        class Meta:
            root = settings.VIDEOS_ARCHIVE_ROOT
            release_date = False
            embargo_date = False
            last_modified = True
            created = True
            published = True
Esempio n. 4
0
class ImageComparison( ArchiveModel, TranslationModel ):
    """
    Image comparisons allows to compare two images with a nice
    JavaScript feature that will reveal the two images when hovering
    the mouse over the image.
    """
    id = archive_fields.IdField()
    priority = archive_fields.PriorityField( help_text=_( u'Assessment of the quality of the image comparison (100 highest, 0 lowest). Higher priority images are ranked higher in search results than lower priority images.' ) )

    featured = models.BooleanField(default=True)

    title = metadatafields.AVMTitleField()
    description = metadatafields.AVMDescriptionField()
    credit = metadatafields.AVMCreditField( default=DEFAULT_CREDIT_FUNC )

    image_before = TranslationForeignKey( Image, related_name='imagecomparison_before_set', null=True )
    image_after = TranslationForeignKey( Image, related_name='imagecomparison_after_set', null=True )

    def __init__( self, *args, **kwargs ):
        super( ImageComparison, self ).__init__( *args, **kwargs )
        if not self.credit:
            self.credit = DEFAULT_CREDIT

    def __unicode__( self ):
        return self.title

    def height_ratio( self ):
        return float( self.image_before.height ) / float( self.image_before.width )

    def height_1280( self ):
        return int( 1280 * self.height_ratio() )

    def get_absolute_url(self):
        return translation_reverse( 'imagecomparisons_detail', args=[str( self.id if self.is_source() else self.source.id )], lang=self.lang )

    class Meta:
        ordering = ( '-priority', '-release_date', )
        app_label = 'media'
        permissions = [
            ( "view_only_non_default", "Can view only non default language" ),
        ]

    class Translation:
        fields = [ 'title', 'description', 'credit', ]
        excludes = [ 'published', 'last_modified', 'created', ]

    class Archive:
        original = ImageResourceManager( type=types.OriginalImageType )
        large = ImageResourceManager( derived='original', type=types.LargeJpegType )
        screen = ImageResourceManager( derived='original', type=types.ScreensizeJpegType )
        news = ImageResourceManager( derived='original', type=types.NewsJpegType )
        newsmini = ImageResourceManager( derived='original', type=types.NewsMiniJpegType )
        newsfeature = ImageResourceManager( derived='original', type=types.NewsFeatureType )
        medium = ImageResourceManager( derived='original', type=types.MediumJpegType )
        wallpaperthumbs = ImageResourceManager( derived='original', type=types.WallpaperThumbnailType )
        potwmedium = ImageResourceManager( derived='original', type=types.POTWMediumThumbnailJpegType )
        thumbs = ImageResourceManager( derived='original', type=types.ThumbnailJpegType )
        thumb350x = ImageResourceManager( derived='original', type=types.Thumb350xType )
        screen640 = ImageResourceManager(derived='original', type=types.Screen640Type)
        thumb300y = ImageResourceManager(derived='original', type=types.Thumb300yType)
        thumb350x = ImageResourceManager(derived='original', type=types.Thumb350xType)
        thumb700x = ImageResourceManager(derived='original', type=types.Thumb700xType)

        class Meta:
            root = getattr( settings, 'IMAGECOMPARISON_ARCHIVE_ROOT', '' )
            release_date = True
            embargo_date = True
            release_date_owner = True
            last_modified = True
            created = True
            published = True
            rename_pk = ( 'media_imagecomparison', 'id' )
            rename_fks = (
                ( 'media_imagecomparison', 'source_id' ),
                ( 'media_image', 'release_date_owner' ),
            )
            sort_fields = ['last_modified', 'release_date', ]
            clean_html_fields = ['description', 'credit']
Esempio n. 5
0
class Announcement(ArchiveModel, TranslationModel):
    """
    Similar to press releases but with fewer fields.
    """
    id = archive_fields.IdField()
    title = archive_fields.TitleField()
    subtitle = models.CharField(
        max_length=255,
        blank=True,
        help_text=_(u"Optional subtitle to be shown just above the headline."))
    description = archive_fields.DescriptionField()
    contacts = models.TextField(blank=True, help_text=_(u'Contacts'))
    links = models.TextField(blank=True, help_text=_(u'Links'))
    featured = models.BooleanField(default=True)
    related_images = TranslationManyToManyField(Image,
                                                through='AnnouncementImage')
    related_videos = TranslationManyToManyField(Video,
                                                through='AnnouncementVideo')
    related_comparisons = TranslationManyToManyField(
        ImageComparison,
        through='AnnouncementImageComparison',
        only_sources=True)

    announcement_type = TranslationForeignKey(AnnouncementType,
                                              blank=True,
                                              null=True,
                                              default=None)

    def get_embargo_login(self):
        return settings.ARCHIVE_EMBARGO_LOGIN

    def _set_main_visual(self, vis):
        self._main_visual_cache = vis

    def _get_main_visual(self):
        try:
            return self._main_visual_cache
        except AttributeError:
            pass

        for visual in self.announcementimage_set.all():
            if visual.main_visual:
                self._main_visual_cache = visual.archive_item
                return visual.archive_item

        for visual in self.announcementimagecomparison_set.all():
            if visual.main_visual:
                self._main_visual_cache = visual.archive_item
                return visual.archive_item

        for visual in self.announcementvideo_set.all():
            if visual.main_visual:
                self._main_visual_cache = visual.archive_item
                return visual.archive_item

        return None

    main_visual = property(_get_main_visual)

    def rename(self, new_pk):
        '''
        Extend Archive's rename() to send email notification if original is renamed
        '''
        if self.published and self.is_source() and hasattr(
                settings, 'ANNOUNCEMENT_RENAME_NOTIFY'):
            msg_subject = 'Announcement renamed: %s -> %s' % (self.pk, new_pk)
            msg_body = """https://www.eso.org/public/announcements/%s/""" % new_pk
            msg_from = getattr(settings, 'DEFAULT_FROM_EMAIL', '')
            msg_to = getattr(settings, 'ANNOUNCEMENT_RENAME_NOTIFY', '')
            if msg_from and msg_to:
                send_mail(msg_subject,
                          msg_body,
                          msg_from,
                          msg_to,
                          fail_silently=False)

        return super(Announcement, self).rename(new_pk)

    @staticmethod
    def store_main_visuals(object_list):
        '''
        Fetches the main image for all announcements in object list using one query, instead
        of one query per announcement.
        '''
        annids = [x.id if x.is_source() else x.source_id for x in object_list]

        images = (AnnouncementImage.objects.filter(
            main_visual=True,
            announcement__in=annids).select_related('archive_item'))
        videos = (AnnouncementVideo.objects.filter(
            main_visual=True,
            announcement__in=annids).select_related('archive_item'))
        comparisons = (AnnouncementImageComparison.objects.filter(
            main_visual=True,
            announcement__in=annids).select_related('archive_item'))

        announcement_mapping = {}
        for video in videos:
            announcement_mapping[video.announcement_id] = video.archive_item
        for image in images:
            announcement_mapping[image.announcement_id] = image.archive_item
        for comparison in comparisons:
            announcement_mapping[
                comparison.announcement_id] = comparison.archive_item

        for obj in object_list:
            try:
                visual = announcement_mapping[obj.id if obj.is_source(
                ) else obj.source_id]
                obj._set_main_visual(visual)
            except KeyError:
                obj._set_main_visual(None)

    @staticmethod
    def get_latest_announcement(len=1, only_featured=False):
        qs = Announcement.objects.filter(release_date__lte=datetime.now(),
                                         published=True)
        if only_featured:
            qs = qs.filter(featured=True)
        return qs.order_by('-release_date')[:len]

    class Meta:
        ordering = ['-release_date', '-id']
        get_latest_by = "release_date"
        permissions = [
            ("view_only_non_default", "Can view only non default language"),
        ]

    def get_absolute_url(self):
        return translation_reverse(
            'announcements_detail',
            args=[str(self.id if self.is_source() else self.source.id)],
            lang=self.lang)

    def __unicode__(self):
        return u"%s: %s" % (self.id, self.title)

    class Translation:
        fields = ['title', 'subtitle', 'description', 'contacts', 'links']
        excludes = [
            'published',
            'last_modified',
            'created',
        ]
        non_default_languages_in_fallback = False  # Don't show non-en anns. if no en translation is available

    class Archive:
        pdf = ResourceManager(type=types.PDFType)
        pdfsm = ResourceManager(type=types.PDFType)
        sciencepaper = ResourceManager(type=types.PDFType,
                                       verbose_name=_('Science paper'))

        class Meta:
            root = ANNOUNCEMENTS_ROOT
            release_date = True
            embargo_date = True
            last_modified = True
            created = True
            published = True
            rename_pk = ('announcements_announcement', 'id')
            rename_fks = (
                ('announcements_announcement', 'source_id'),
                ('announcements_announcementimage', 'announcement_id'),
                ('announcements_announcementvideo', 'announcement_id'),
                ('media_image', 'release_date_owner'),
                ('media_video', 'release_date_owner'),
                ('media_imagecomparison', 'release_date_owner'),
            )
            sort_fields = ['last_modified', 'release_date']
            clean_html_fields = ['description', 'links', 'contacts']
Esempio n. 6
0
class VideoSubtitle( ArchiveModel, models.Model ):
    """
    Model for storing subtitles for videos.
    """
    id = archive_fields.IdField()
    video = TranslationForeignKey( Video )
    lang = models.CharField( verbose_name=_( 'Language' ), max_length=7, choices=SUBTITLE_LANGUAGES, default=settings.LANGUAGE_CODE, db_index=True )

    def save( self, **kwargs ):
        """
        Override save() to always set id as video_id + lang

        # TODO: check video renaming
        """
        old_id = self.id
        self.id = self.video.id + self.lang

        if old_id != self.id:  # delete old
            try:
                old = VideoSubtitle.objects.get( id=old_id )
                old.delete()
            except VideoSubtitle.DoesNotExist:
                pass

        # In some cases where 'created' was not set upon creation the save
        # will fail so we manually set it
        if not self.created:  # pylint: disable=E0203
            self.created = datetime.datetime.today()

        super( VideoSubtitle, self ).save( **kwargs )

        transaction.on_commit(
            lambda: update_youtube_caption.delay(self.pk)
        )

    def __unicode__( self ):
        return dict( SUBTITLE_LANGUAGES ).get( self.lang, self.lang )

    def update_youtube_caption(self, logger=None):
        '''
        Upload the given subtitle to YouTube
        '''
        if logger is None:
            logger = logging.getLogger(__name__)

        if not youtube_configured or not self.video or not self.video.youtube_video_id:
            logger.warning('No video or YouTube ID for subtitle "%s"', self.pk)
            return

        response = youtube_videos_list(
            id=self.video.youtube_video_id,
            part='snippet'
        )

        if not response['items']:
            raise YouTubeUnknownID('Unkown YouTube ID: "%s"' %
                    self.youtube_video_id)

        snippet = dict(
            videoId=self.video.youtube_video_id,
            language=self.lang,
            name='',
            isDraft=False
        )

        # Check if caption already exists
        response = youtube_captions_list(
            part='snippet',
            video_id=self.video.youtube_video_id
        )

        # We use wait_for_resource in case the NFS is slow to synchronise
        # between the different servers
        srt = wait_for_resource(self, 'srt')

        for item in response['items']:
            if item['snippet']['language'] == self.lang:
                # Subtitle already exist, we update it
                youtube_captions_update(
                    part='snippet',
                    body=dict(
                        id=item['id'],
                        snippet=snippet
                    ),
                    media_body=srt.file.name
                )
                break
        else:
            # New subtitle, we insert it
            youtube_captions_insert(
                part='snippet',
                body=dict(
                    snippet=snippet
                ),
                media_body=srt.file.name
            )

    class Meta:
        verbose_name = _(u'Video Subtitle')
        app_label = 'media'

    class Archive:
        srt = ResourceManager( type=types.SubtitleType, verbose_name=_( u"Subtitle (srt)" ) )

        class Meta:
            root = settings.VIDEOS_ARCHIVE_ROOT
            release_date = False
            embargo_date = False
            last_modified = True
            created = True
            published = True
Esempio n. 7
0
class PictureOfTheWeek(ArchiveModel, TranslationModel):
    """
    Model representing that an picture of the week. The model
    can either use an image or a video as it's main visual. The release date
    set will be propagate to the image/video model.
    """
    id = archive_fields.IdField()
    image = TranslationForeignKey(Image,
                                  blank=True,
                                  null=True,
                                  only_sources=False)
    video = TranslationForeignKey(Video,
                                  blank=True,
                                  null=True,
                                  only_sources=False)
    comparison = models.ForeignKey(ImageComparison, blank=True, null=True)
    auto_update = True

    def visual(self):
        """
        Obtain either an image or a video if specified.
        """
        if self.image:
            return self.image
        elif self.video:
            return self.video
        elif self.comparison:
            return self.comparison
        else:
            return None

    def get_absolute_url(self):
        """
        URL of image or video detail view, since POTW does not
        use its own detail view.
        """
        v = self.visual()
        return v.get_absolute_url() if v else None

    def rename(self, new_pk):
        '''
        Extend Archive's rename() to send email notification if original is renamed
        '''
        if self.published and self.is_source() and hasattr(
                settings, 'RELEASE_RENAME_NOTIFY'):
            msg_subject = 'Picture of the Week renamed: %s -> %s' % (self.pk,
                                                                     new_pk)
            msg_body = """https://www.eso.org/public/images/%s/""" % new_pk
            msg_from = getattr(settings, 'DEFAULT_FROM_EMAIL', '')
            msg_to = getattr(settings, 'POTW_RENAME_NOTIFY', '')
            if msg_from and msg_to:
                send_mail(msg_subject,
                          msg_body,
                          msg_from,
                          msg_to,
                          fail_silently=False)

        return super(PictureOfTheWeek, self).rename(new_pk)

    def save(self, **kwargs):
        signals.post_save.disconnect(PictureOfTheWeek.post_save_handler,
                                     sender=PictureOfTheWeek)
        signals.post_save.disconnect(
            PictureOfTheWeek.post_related_save_handler, sender=Image)
        signals.post_save.disconnect(
            PictureOfTheWeek.post_related_save_handler, sender=ImageProxy)
        signals.post_save.disconnect(
            PictureOfTheWeek.post_related_save_handler, sender=Video)
        signals.post_save.disconnect(
            PictureOfTheWeek.post_related_save_handler, sender=VideoProxy)
        signals.post_save.disconnect(
            PictureOfTheWeek.post_related_save_handler, sender=ImageComparison)
        signals.post_save.disconnect(
            PictureOfTheWeek.post_related_save_handler,
            sender=ImageComparisonProxy)
        super(PictureOfTheWeek, self).save(**kwargs)
        signals.post_save.connect(PictureOfTheWeek.post_save_handler,
                                  sender=PictureOfTheWeek)
        signals.post_save.connect(PictureOfTheWeek.post_related_save_handler,
                                  sender=Image)
        signals.post_save.connect(PictureOfTheWeek.post_related_save_handler,
                                  sender=ImageProxy)
        signals.post_save.connect(PictureOfTheWeek.post_related_save_handler,
                                  sender=Video)
        signals.post_save.connect(PictureOfTheWeek.post_related_save_handler,
                                  sender=VideoProxy)
        signals.post_save.connect(PictureOfTheWeek.post_related_save_handler,
                                  sender=ImageComparison)
        signals.post_save.connect(PictureOfTheWeek.post_related_save_handler,
                                  sender=ImageComparisonProxy)

    @classmethod
    def get_latest(cls):
        """
        Method to get the latest public POTW
        """
        try:
            now = datetime.now()
            im = cls.objects.filter(
                published=True, release_date__lt=now,
                embargo_date__lt=now).order_by('-release_date')[0]
            return im
        except IndexError:
            raise cls.DoesNotExist

    def __unicode__(self):
        v = self.visual()
        return "%s - %s" % (self.id, v.title) if v else self.id

    @classmethod
    def post_save_handler(cls,
                          sender,
                          instance=None,
                          created=False,
                          raw=False,
                          **kwargs):
        """
        Automatically create/delete POTW translations for images/videos/comparisons.
        """
        if instance.auto_update and not raw:
            # Delete all translations and add new ones
            instance.translations.all().delete()
            for attr in [
                    'image',
                    'comparison',
                    'video',
            ]:
                # If related object exists and has translations, then
                # create corresponding potw translations for all.
                related_object = getattr(instance, attr)
                if related_object and isinstance(related_object,
                                                 TranslationModel):
                    for related_obj_trans in related_object.translations.all():
                        potw_trans = PictureOfTheWeekProxy(
                            **{
                                attr: related_obj_trans,
                                'lang': related_obj_trans.lang,
                                'source': instance,
                                'translation_ready':
                                related_obj_trans.translation_ready,
                                'published': related_obj_trans.published,
                            })
                        potw_trans.clean()
                        potw_trans.save()
                    # Stop processing since we can only have one
                    # image, comparison or video defined at a given time.
                    break

    @classmethod
    def post_related_save_handler(cls,
                                  sender,
                                  instance=None,
                                  created=False,
                                  raw=False,
                                  **kwargs):
        """
        Once a related object is saved, we might need to run post_save_handle for the POTW
        """
        if not raw:
            if isinstance(instance, TranslationModel):
                instance = instance if instance.is_source(
                ) else instance.source
                for potw in instance.pictureoftheweek_set.all():
                    cls.post_save_handler(sender,
                                          instance=potw,
                                          created=created,
                                          raw=raw)

    class Meta:
        ordering = ('-release_date', )
        verbose_name_plural = _('Pictures of the Week')
        app_label = 'media'
        permissions = [
            ("view_only_non_default", "Can view only non default language"),
        ]

    class Translation:
        fields = ['image', 'video', 'comparison']
        excludes = [
            'published',
            'last_modified',
            'created',
        ]

    class Archive:
        class Meta:
            release_date = True
            embargo_date = True
            last_modified = True
            created = True
            published = True
            rename_pk = ('media_pictureoftheweek', 'id')
            rename_fks = (
                ('media_pictureoftheweek', 'source_id'),
                ('media_image', 'release_date_owner'),
                ('media_video', 'release_date_owner'),
                ('media_imagecomparison', 'release_date_owner'),
            )
            sort_fields = ['last_modified', 'release_date']
Esempio n. 8
0
class ScienceAnnouncement(ArchiveModel, TranslationModel):
    """
    Similar to press releases but with fewer fields.
    """
    id = archivesfields.IdField()
    title = archivesfields.TitleField()
    subtitle = models.CharField(max_length=255, blank=True, help_text=_(u"Optional subtitle to be shown just above the headline."))
    description = archivesfields.DescriptionField()
    contacts = models.TextField(blank=True, help_text=_(u'Contacts'))
    links = models.TextField(blank=True, help_text=_(u'Links'))
    featured = models.BooleanField(default=True)
    related_images = models.ManyToManyField(Image, through='ScienceAnnouncementImage')

    def _set_main_visual(self, vis):
        self._main_visual_cache = vis

    def _get_main_visual(self):
        try:
            return self._main_visual_cache
        except AttributeError:
            try:
                vis = ScienceAnnouncementImage.objects.filter(main_visual=True, science_announcement=self).get()
                self._main_visual_cache = vis.archive_item
                return vis.archive_item
            except IndexError:
                return None
            except ScienceAnnouncementImage.DoesNotExist:
                return None

    main_visual = property(_get_main_visual)

    class Meta:
        ordering = ['-release_date', '-id']
        get_latest_by = "release_date"
        permissions = [
            ("view_only_non_default", "Can view only non default language"),
        ]

    def get_absolute_url(self):
        return reverse('scienceannouncements_detail', args=[str(self.id)])

    def __unicode__(self):
        return u"%s: %s" % (self.id, self.title)

    class Archive:
        pdf = ResourceManager(type=types.PDFType)
        pdfsm = ResourceManager(type=types.PDFType)
        sciencepaper = ResourceManager(type=types.PDFType, verbose_name=_('Science paper'))

        class Meta:
            root = settings.SCIENCEANNOUNCEMENTS_ARCHIVE_ROOT
            release_date = True
            embargo_date = True
            last_modified = True
            created = True
            published = True
            rename_pk = ('science_scienceannouncement', 'id')
            rename_fks = (
                ('media_image', 'release_date_owner'),
                ('science_scienceannouncementimage', 'science_announcement_id'),
            )
            sort_fields = ['last_modified', 'release_date', ]