diff options
| author | Étienne Loks <etienne.loks@iggdrasil.net> | 2018-05-10 16:53:30 +0200 | 
|---|---|---|
| committer | Étienne Loks <etienne.loks@iggdrasil.net> | 2018-06-12 08:44:18 +0200 | 
| commit | 3d12b0ac2e97ab43a555106f404ed7cf442caf17 (patch) | |
| tree | 76b335690d709db53f269849b93f6b99e7e1fd7c /ishtar_common/models.py | |
| parent | 43c017bc8dd00372f26728130b00b1cd9196fb10 (diff) | |
| download | Ishtar-3d12b0ac2e97ab43a555106f404ed7cf442caf17.tar.bz2 Ishtar-3d12b0ac2e97ab43a555106f404ed7cf442caf17.zip | |
Move image to logical directory and generate symlinks (refs #4076)
Diffstat (limited to 'ishtar_common/models.py')
| -rw-r--r-- | ishtar_common/models.py | 135 | 
1 files changed, 128 insertions, 7 deletions
| diff --git a/ishtar_common/models.py b/ishtar_common/models.py index d4d6d2c79..0e8d96ddb 100644 --- a/ishtar_common/models.py +++ b/ishtar_common/models.py @@ -27,7 +27,6 @@ import inspect  from PIL import Image  import logging  import os -from os.path import isfile, join  import re  from secretary import Renderer as SecretaryRenderer  import shutil @@ -939,10 +938,7 @@ class ImageModel(models.Model):                      pass              # save the thumbnail -            splited = filename.split('.') -            thumb_filename = u"{}-thumb.{}".format( -                u".".join(splited[:-1]), splited[-1] -            ) +            thumb_filename = self._get_thumb_name(filename)              self.thumbnail.save(                  thumb_filename,                  self.create_thumb(image, self.THUMB_MAX_SIZE), @@ -951,6 +947,12 @@ class ImageModel(models.Model):              pass          return super(ImageModel, self).save(*args, **kwargs) +    def _get_thumb_name(self, filename): +        splited = filename.split('.') +        return u"{}-thumb.{}".format( +            u".".join(splited[:-1]), splited[-1] +        ) +  class HistoryError(Exception):      def __init__(self, value): @@ -3041,8 +3043,18 @@ class ImageType(GeneralType):  class IshtarImage(ImageModel): +    # order is important: put the image in the first match found +    # other will be symbolic links +    RELATED_MODELS = [ +        'treatmentimage_set', 'findimage_set', 'contextrecordimage_set', +        'operationimage_set', 'siteimage_set', 'warehouseimage_set', +    ] +    LINK_SPLIT = u"<||>" +      name = models.CharField(_(u"Name"), max_length=250, blank=True, null=True)      description = models.TextField(_(u"Description"), blank=True, null=True) +    associated_links = models.TextField(_(u"Symbolic links"), blank=True, +                                        null=True)      licenses = models.ManyToManyField(LicenseType, verbose_name=_(u"License"),                                        blank=True)      authors = models.ManyToManyField(Author, verbose_name=_(u"Authors"), @@ -3064,6 +3076,115 @@ class IshtarImage(ImageModel):          verbose_name_plural = _(u"Images")          ordering = ('name',) +    def _get_base_image_paths(self): +        for related_model in self.RELATED_MODELS: +            q = getattr(self, related_model).all() +            if q.count(): +                item = q.all()[0].item +                yield item._get_base_image_path() + +    def _get_base_image_path(self): +        for path in self._get_base_image_paths(): +            return path +        return u"upload" + +    def _get_available_filename(self, path, test_link=None): +        """ +        Get a filename not used +        If name already used - generate a name with schema: +        [base]-[current_number + 1].[suffix] + +        :param path: base path +        :param test_link: test if an existing path match with this link +        :return: if test_link is not None, (new_path, link_match) otherwise +        the new_path +        """ + +        file_split = path.split('.') +        suffix, base = "", "" +        if len(file_split) > 1: +            base = u".".join(file_split[0:-1]) +            suffix = file_split[-1] +        else: +            base = path +        base_split = base.split('-') +        current_nb = 0 +        if len(base_split) > 1: +            try: +                current_nb = int(base_split[-1]) +                base = u"-".join(base_split[0:-1]) + u"-" +            except ValueError: +                pass + +        while os.path.exists(path): +            if test_link and os.path.islink(path) \ +                    and os.readlink(path) == test_link: +                return path, True +            current_nb += 1 +            path = u"{}-{}.{}".format(base, current_nb, suffix) +        if test_link: +            return path, False +        return path + +    def _move_image(self): +        """ +        Move to the relevant path and create appropriate symbolic links + +        :return: list of associated links +        """ +        reference_path = None +        initial_path = self.image.path +        filename = os.path.basename(initial_path) +        links = [] + +        for related_model in self.RELATED_MODELS: +            q = getattr(self, related_model).all() +            if q.count(): +                item = q.all()[0].item +                base_path = item._get_base_image_path() +                new_path = base_path + u"/" + filename +                if not reference_path: +                    reference_path = settings.MEDIA_ROOT + new_path +                    # correct path +                    if initial_path == reference_path: +                        continue +                    if not os.path.exists(os.path.dirname(reference_path)): +                        os.makedirs(os.path.dirname(reference_path)) + +                    reference_path = self._get_available_filename( +                        reference_path) + +                    os.rename(initial_path, reference_path) +                    os.rename(self.thumbnail.path, +                              self._get_thumb_name(reference_path)) +                    self.image.name = reference_path[len(settings.MEDIA_ROOT):] +                    self.save(no_path_change=True) +                    continue +                # create a link +                new_path = settings.MEDIA_ROOT + new_path +                if not os.path.exists(os.path.dirname(new_path)): +                    os.makedirs(os.path.dirname(new_path)) +                new_path, match = self._get_available_filename( +                    new_path, test_link=reference_path) +                links.append(new_path) +                if match:  # the current link is correct +                    continue +                os.symlink(reference_path, new_path) +        return links + +    def save(self, *args, **kwargs): +        no_path_change = 'no_path_change' in kwargs \ +                         and kwargs.pop('no_path_change') + +        super(IshtarImage, self).save(*args, **kwargs) + +        if not no_path_change and not getattr(self, '_no_path_change', False): +            links = self._move_image() +            links = self.LINK_SPLIT.join(links) +            if links != self.associated_links: +                self.associated_links = links +                self.save(no_path_change=True) +  class ThroughImage(models.Model):      image = models.ForeignKey( @@ -3414,8 +3535,8 @@ class AdministrationTask(models.Model):          # only script inside the script directory can be executed          for name in os.listdir(script_dir):              if name == self.script.path: -                if isfile(join(script_dir, name)): -                    script_name = join(script_dir, name) +                if os.path.isfile(os.path.join(script_dir, name)): +                    script_name = os.path.join(script_dir, name)                  break          if not script_name:              self.result = unicode( | 
