Generated: Wed 2013-03-13 10:33 CET
Source file: /media/Envs/Envs/filer-gallery/lib/python2.7/site-packages/filer/models/filemodels.py
Stats: 0 executed, 147 missed, 19 excluded, 121 ignored
#-*- coding: utf-8 -*-from django.contrib.auth import models as auth_modelsfrom django.core import urlresolversfrom django.core.files.base import ContentFilefrom django.db import modelsfrom django.utils.translation import ugettext_lazy as _from filer.fields.multistorage_file import MultiStorageFileFieldfrom filer.models import mixinsfrom filer import settings as filer_settingsfrom filer.models.foldermodels import Folderfrom polymorphic import PolymorphicModel, PolymorphicManagerimport hashlibimport osclass FileManager(PolymorphicManager): def find_all_duplicates(self): r = {} for file_obj in self.all(): if file_obj.sha1: q = self.filter(sha1=file_obj.sha1) if len(q) > 1: r[file_obj.sha1] = q return r def find_duplicates(self, file_obj): return [i for i in self.exclude(pk=file_obj.pk).filter(sha1=file_obj.sha1)]class File(PolymorphicModel, mixins.IconsMixin): file_type = 'File' _icon = "file" folder = models.ForeignKey(Folder, verbose_name=_('folder'), related_name='all_files', null=True, blank=True) file = MultiStorageFileField(_('file'), null=True, blank=True, max_length=255) _file_size = models.IntegerField(_('file size'), null=True, blank=True) sha1 = models.CharField(_('sha1'), max_length=40, blank=True, default='') has_all_mandatory_data = models.BooleanField(_('has all mandatory data'), default=False, editable=False) original_filename = models.CharField(_('original filename'), max_length=255, blank=True, null=True) name = models.CharField(max_length=255, default="", blank=True, verbose_name=_('name')) description = models.TextField(null=True, blank=True, verbose_name=_('description')) owner = models.ForeignKey(auth_models.User, related_name='owned_%(class)ss', null=True, blank=True, verbose_name=_('owner')) uploaded_at = models.DateTimeField(_('uploaded at'), auto_now_add=True) modified_at = models.DateTimeField(_('modified at'), auto_now=True) is_public = models.BooleanField( default=filer_settings.FILER_IS_PUBLIC_DEFAULT, verbose_name=_('Permissions disabled'), help_text=_('Disable any permission checking for this ' +\ 'file. File will be publicly accessible ' +\ 'to anyone.')) objects = FileManager() @classmethod def matches_file_type(cls, iname, ifile, request): return True # I match all files... def __init__(self, *args, **kwargs): super(File, self).__init__(*args, **kwargs) self._old_is_public = self.is_public def _move_file(self): """ Move the file from src to dst. """ src_file_name = self.file.name dst_file_name = self._meta.get_field('file').generate_filename( self, self.original_filename) if self.is_public: src_storage = self.file.storages['private'] dst_storage = self.file.storages['public'] else: src_storage = self.file.storages['public'] dst_storage = self.file.storages['private'] # delete the thumbnail # We are toggling the is_public to make sure that easy_thumbnails can # delete the thumbnails self.is_public = not self.is_public self.file.delete_thumbnails() self.is_public = not self.is_public # This is needed because most of the remote File Storage backend do not # open the file. src_file = src_storage.open(src_file_name) src_file.open() self.file = dst_storage.save(dst_file_name, ContentFile(src_file.read())) src_storage.delete(src_file_name) def _copy_file(self, destination, overwrite=False): """ Copies the file to a destination files and returns it. """ if overwrite: # If the destination file already exists default storage backend # does not overwrite it but generates another filename. # TODO: Find a way to override this behavior. raise NotImplementedError src_file_name = self.file.name storage = self.file.storages['public' if self.is_public else 'private'] # This is needed because most of the remote File Storage backend do not # open the file. src_file = storage.open(src_file_name) src_file.open() return storage.save(destination, ContentFile(src_file.read())) def generate_sha1(self): sha = hashlib.sha1() self.file.seek(0) sha.update(self.file.read()) self.sha1 = sha.hexdigest() # to make sure later operations can read the whole file self.file.seek(0) def save(self, *args, **kwargs): # check if this is a subclass of "File" or not and set # _file_type_plugin_name if self.__class__ == File: # what should we do now? # maybe this has a subclass, but is being saved as a File instance # anyway. do we need to go check all possible subclasses? pass elif issubclass(self.__class__, File): self._file_type_plugin_name = self.__class__.__name__ # cache the file size # TODO: only do this if needed (depending on the storage backend the whole file will be downloaded) try: self._file_size = self.file.size except: pass if self._old_is_public != self.is_public and self.pk: self._move_file() self._old_is_public = self.is_public # generate SHA1 hash # TODO: only do this if needed (depending on the storage backend the whole file will be downloaded) try: self.generate_sha1() except Exception, e: pass super(File, self).save(*args, **kwargs) save.alters_data = True def delete(self, *args, **kwargs): # Delete the model before the file super(File, self).delete(*args, **kwargs) # Delete the file if there are no other Files referencing it. if not File.objects.filter(file=self.file.name, is_public=self.is_public).exists(): self.file.delete(False) delete.alters_data = True @property def label(self): if self.name in ['', None]: text = self.original_filename or 'unnamed file' else: text = self.name text = u"%s" % (text,) return text def __lt__(self, other): return cmp(self.label.lower(), other.label.lower()) < 0 def has_edit_permission(self, request): return self.has_generic_permission(request, 'edit') def has_read_permission(self, request): return self.has_generic_permission(request, 'read') def has_add_children_permission(self, request): return self.has_generic_permission(request, 'add_children') def has_generic_permission(self, request, permission_type): """ Return true if the current user has permission on this image. Return the string 'ALL' if the user has all rights. """ user = request.user if not user.is_authenticated(): return False elif user.is_superuser: return True elif user == self.owner: return True elif self.folder: return self.folder.has_generic_permission(request, permission_type) else: return False def __unicode__(self): if self.name in ('', None): text = u"%s" % (self.original_filename,) else: text = u"%s" % (self.name,) return text def get_admin_url_path(self): return urlresolvers.reverse( 'admin:%s_%s_change' % (self._meta.app_label, self._meta.module_name,), args=(self.pk,) ) @property def file_ptr(self): """ Evil hack to get around the cascade delete problem with django_polymorphic. Prevents ``AttributeError: 'File' object has no attribute 'file_ptr'``. This is only a workaround for one level of subclassing. The hierarchy of object in the admin delete view is wrong, but at least it works. """ return self @property def url(self): """ to make the model behave like a file field """ try: r = self.file.url except: r = '' return r @property def path(self): try: return self.file.path except: return "" @property def size(self): return self._file_size or 0 @property def extension(self): filetype = os.path.splitext(self.file.name)[1].lower() if len(filetype) > 0: filetype = filetype[1:] return filetype @property def logical_folder(self): """ if this file is not in a specific folder return the Special "unfiled" Folder object """ if not self.folder: from filer.models.virtualitems import UnfiledImages return UnfiledImages() else: return self.folder @property def logical_path(self): """ Gets logical path of the folder in the tree structure. Used to generate breadcrumbs """ folder_path = [] if self.folder: folder_path.extend(self.folder.get_ancestors()) folder_path.append(self.logical_folder) return folder_path @property def duplicates(self): return File.objects.find_duplicates(self) class Meta: app_label = 'filer' verbose_name = _('file') verbose_name_plural = _('files')