Files
mayan-edms/apps/documents/models.py

194 lines
7.9 KiB
Python

import errno
import os
import mimetypes
from datetime import datetime
from django.conf import settings
from django.db import models
from django.template.defaultfilters import slugify
from django.utils.translation import ugettext_lazy as _
from django.utils.translation import ugettext
from dynamic_search.api import register
from documents.conf.settings import AVAILABLE_FUNCTIONS
from documents.conf.settings import AVAILABLE_MODELS
from documents.conf.settings import CHECKSUM_FUNCTION
from documents.conf.settings import UUID_FUNCTION
from documents.conf.settings import STORAGE_BACKEND
from documents.conf.settings import STORAGE_DIRECTORY_NAME
from documents.conf.settings import FILESYSTEM_FILESERVING_ENABLE
from documents.conf.settings import FILESYSTEM_FILESERVING_PATH
from documents.conf.settings import FILESYSTEM_SLUGIFY_PATHS
if FILESYSTEM_SLUGIFY_PATHS == False:
#Do not slugify path or filenames and extensions
slugify = lambda x:x
def get_filename_from_uuid(instance, filename, directory=STORAGE_DIRECTORY_NAME):
populate_file_extension_and_mimetype(instance, filename)
return '%s/%s' % (directory, instance.uuid)
def populate_file_extension_and_mimetype(instance, filename):
# First populate the file extension and mimetype
instance.file_mimetype, encoding = mimetypes.guess_type(filename)
if not instance.file_mimetype:
instance.file_mimetype = u'unknown'
filename, extension = os.path.splitext(filename)
instance.file_filename = filename
#remove prefix '.'
instance.file_extension = extension[1:]
class DocumentType(models.Model):
name = models.CharField(max_length=32, verbose_name=_(u'name'))
def __unicode__(self):
return self.name
class Document(models.Model):
""" Minimum fields for a document entry.
Inherit this model to customise document metadata, see BasicDocument for an example.
"""
document_type = models.ForeignKey(DocumentType, verbose_name=_(u'document type'))
file = models.FileField(upload_to=get_filename_from_uuid, storage=STORAGE_BACKEND(), verbose_name=_(u'file'))
uuid = models.CharField(max_length=48, default=UUID_FUNCTION(), blank=True, editable=False)
file_mimetype = models.CharField(max_length=64, default='', editable=False)
file_filename = models.CharField(max_length=64, default='', editable=False)
file_extension = models.CharField(max_length=16, default='', editable=False)
date_added = models.DateTimeField(verbose_name=_(u'added'), auto_now_add=True)
date_updated = models.DateTimeField(verbose_name=_(u'updated'), auto_now=True)
checksum = models.TextField(blank=True, null=True, verbose_name=_(u'checksum'), editable=False)
class Meta:
verbose_name = _(u'document')
verbose_name_plural = _(u'documents')
ordering = ['-date_updated', '-date_added']
def __unicode__(self):
return self.uuid
@models.permalink
def get_absolute_url(self):
return ('document_view', [self.id])
def update_checksum(self, save=True):
self.checksum = unicode(CHECKSUM_FUNCTION(self.file.read()))
if save:
self.save()
def exists(self):
return self.file.storage.exists(self.file.url)
def save(self, *args, **kwargs):
self.update_checksum(save=False)
super(Document, self).save(*args, **kwargs)
def delete(self, *args, **kwargs):
self.delete_fs_links()
super(Document, self).delete(*args, **kwargs)
def calculate_fs_links(self):
targets = []
for metadata in self.documentmetadata_set.all():
if metadata.metadata_type.documenttypemetadatatype_set.all()[0].create_directory_link:
target_directory = os.path.join(FILESYSTEM_FILESERVING_PATH, slugify(metadata.metadata_type.name), slugify(metadata.value))
targets.append(os.path.join(target_directory, os.extsep.join([slugify(self.file_filename), slugify(self.file_extension)])))
return targets
def create_fs_links(self):
if FILESYSTEM_FILESERVING_ENABLE:
for target in self.calculate_fs_links():
try:
os.makedirs(os.path.dirname(target))
except OSError, exc:
if exc.errno == errno.EEXIST:
pass
else:
raise OSError(ugettext(u'Unable to create metadata indexing directory: %s') % exc)
try:
os.symlink(os.path.abspath(self.file.path), target)
except OSError, exc:
if exc.errno == errno.EEXIST:
pass
else:
raise OSError(ugettext(u'Unable to create metadata indexing symbolic link: %s') % exc)
def delete_fs_links(self):
if FILESYSTEM_FILESERVING_ENABLE:
for target in self.calculate_fs_links():
try:
os.unlink(target)
except OSError, exc:
if exc.errno == errno.ENOENT:
pass
else:
raise OSError(ugettext(u'Unable to delete metadata indexing symbolic link: %s') % exc)
available_functions_string = (_(u' Available functions: %s') % ','.join(['%s()' % name for name, function in AVAILABLE_FUNCTIONS.items()])) if AVAILABLE_FUNCTIONS else ''
available_models_string = (_(u' Available models: %s') % ','.join([name for name, model in AVAILABLE_MODELS.items()])) if AVAILABLE_MODELS else ''
class MetadataType(models.Model):
name = models.CharField(max_length=48, verbose_name=_(u'name'))
default = models.CharField(max_length=128, blank=True, null=True,
verbose_name=_(u'default'), help_text=_(u'Enter a string to be evaluated.%s') % available_functions_string)
lookup = models.CharField(max_length=128, blank=True, null=True,
verbose_name=_(u'lookup'), help_text=_(u'Enter a string to be evaluated. Example: [user.get_full_name() for user in User.objects.all()].%s') % available_models_string)
#datatype = models.
def __unicode__(self):
return self.name
class Meta:
verbose_name = _(u'metadata type')
verbose_name_plural = _(u'metadata types')
class DocumentTypeMetadataType(models.Model):
document_type = models.ForeignKey(DocumentType, verbose_name=_(u'document type'))
metadata_type = models.ForeignKey(MetadataType, verbose_name=_(u'metadata type'))
create_directory_link = models.BooleanField(verbose_name=_(u'create directory link'))
#override default
#required? -bool
def __unicode__(self):
return unicode(self.metadata_type)
class Meta:
verbose_name = _(u'document type metadata type connector')
verbose_name_plural = _(u'document type metadata type connectors')
class DocumentMetadata(models.Model):
document = models.ForeignKey(Document, verbose_name=_(u'document'))
metadata_type = models.ForeignKey(MetadataType, verbose_name=_(u'metadata type'))
value = models.TextField(blank=True, null=True, verbose_name=_(u'metadata value'))
def __unicode__(self):
return unicode(self.metadata_type)
class Meta:
verbose_name = _(u'document metadata')
verbose_name_plural = _(u'document metadata')
class DocumentTypeFilename(models.Model):
document_type = models.ForeignKey(DocumentType, verbose_name=_(u'document type'))
filename = models.CharField(max_length=64, verbose_name=_(u'filename'))
enabled = models.BooleanField(default=True, verbose_name=_(u'enabled'))
def __unicode__(self):
return self.filename
class Meta:
ordering = ['filename']
verbose_name = _(u'document type filename')
verbose_name_plural = _(u'document types filenames')
register(Document, _(u'document'), ['document_type__name', 'file_mimetype', 'file_filename', 'file_extension', 'documentmetadata__value'])