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

200 lines
8.0 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 FILESERVING_PATH
from documents.conf.settings import SLUGIFY_PATH
from documents.conf.settings import CHECKSUM_FUNCTION
from documents.conf.settings import UUID_FUNCTION
from documents.conf.settings import STORAGE_DIRECTORY_NAME
if SLUGIFY_PATH == 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)
stem, extension = os.path.splitext(filename)
return '%s/%s%s' % (directory, instance.uuid, extension)
def populate_file_extension_and_mimetype(instance):#, filename):
filename = instance.file.name
# 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 DocumentFile(models.Model):
file = models.FileField(upload_to=get_filename_from_uuid)
file_mimetype = models.CharField(max_length=50, default='', editable=False)
file_filename = models.CharField(max_length=64, default='', editable=False)
file_extension = models.CharField(max_length=10, default='', editable=False)
checksum = models.TextField(blank=True, null=True, verbose_name=_(u'checksum'), editable=False)
class Meta:
verbose_name = _(u'document file')
verbose_name_plural = _(u'documents files')
def __unicode__(self):
return self.id
def update_checksum(self, save=True):
self.checksum = unicode(CHECKSUM_FUNCTION(self.file.read()))
if save:
self.save()
def save(self, *args, **kwargs):
self.update_checksum(save=False)
populate_file_extension_and_mimetype(self)
super(DocumentFile, self).save(*args, **kwargs)
def delete(self, *args, **kwargs):
self.delete_fs_links()
super(DocumentFile, 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(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):
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):
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)
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, blank=True, null=True)
uuid = models.CharField(max_length=36, default=UUID_FUNCTION(), blank=True, editable=False)
#file_mimetype = models.CharField(max_length=50, default='', editable=False)
#file_filename = models.CharField(max_length=64, default='', editable=False)
#file_extension = models.CharField(max_length=10, 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)
document_file = models.ForeignKey(DocumentFile, blank=True, null=True, verbose_name=_('document file'))
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])
available_functions_string = (_(u' Available functions: %s') % ','.join(['%s()' % name for name, function in AVAILABLE_FUNCTIONS.items()])) if AVAILABLE_FUNCTIONS else ''
class MetadataType(models.Model):
name = models.CharField(max_length=32, verbose_name=_(u'name'))
default = models.CharField(max_length=64, 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=64, blank=True, null=True, verbose_name=_(u'lookup'))
#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'])