Files
mayan-edms/mayan/apps/documents/models/document_models.py
Roberto Rosario c7e9a4dc99 Add keyword arguments
Signed-off-by: Roberto Rosario <roberto.rosario.gonzalez@gmail.com>
2019-05-12 02:09:26 -04:00

254 lines
8.1 KiB
Python

from __future__ import absolute_import, unicode_literals
import logging
import uuid
from django.apps import apps
from django.core.files import File
from django.db import models
from django.urls import reverse
from django.utils.encoding import python_2_unicode_compatible
from django.utils.timezone import now
from django.utils.translation import ugettext, ugettext_lazy as _
from ..events import (
event_document_create, event_document_properties_edit,
event_document_type_change,
)
from ..managers import DocumentManager, PassthroughManager, TrashCanManager
from ..settings import setting_language
from ..signals import post_document_type_change
from .document_type_models import DocumentType
__all__ = ('Document',)
logger = logging.getLogger(__name__)
@python_2_unicode_compatible
class Document(models.Model):
"""
Defines a single document with it's fields and properties
Fields:
* uuid - UUID of a document, universally Unique ID. An unique identifier
generated for each document. No two documents can ever have the same UUID.
This ID is generated automatically.
"""
uuid = models.UUIDField(
default=uuid.uuid4, editable=False, help_text=_(
'UUID of a document, universally Unique ID. An unique identifier'
'generated for each document.'
), verbose_name=_('UUID')
)
document_type = models.ForeignKey(
on_delete=models.CASCADE, related_name='documents', to=DocumentType,
verbose_name=_('Document type')
)
label = models.CharField(
blank=True, db_index=True, default='', max_length=255,
help_text=_('The name of the document.'), verbose_name=_('Label')
)
description = models.TextField(
blank=True, default='', help_text=_(
'An optional short text describing a document.'
), verbose_name=_('Description')
)
date_added = models.DateTimeField(
auto_now_add=True, db_index=True, help_text=_(
'The server date and time when the document was finally '
'processed and added to the system.'
), verbose_name=_('Added')
)
language = models.CharField(
blank=True, default=setting_language.value, help_text=_(
'The dominant language in the document.'
), max_length=8, verbose_name=_('Language')
)
in_trash = models.BooleanField(
db_index=True, default=False, help_text=_(
'Whether or not this document is in the trash.'
), editable=False, verbose_name=_('In trash?')
)
# TODO: set editable to False
deleted_date_time = models.DateTimeField(
blank=True, editable=True, help_text=_(
'The server date and time when the document was moved to the '
'trash.'
), null=True, verbose_name=_('Date and time trashed')
)
is_stub = models.BooleanField(
db_index=True, default=True, editable=False, help_text=_(
'A document stub is a document with an entry on the database but '
'no file uploaded. This could be an interrupted upload or a '
'deferred upload via the API.'
), verbose_name=_('Is stub?')
)
objects = DocumentManager()
passthrough = PassthroughManager()
trash = TrashCanManager()
class Meta:
ordering = ('label',)
verbose_name = _('Document')
verbose_name_plural = _('Documents')
def __str__(self):
return self.label or ugettext('Document stub, id: %d') % self.pk
def add_as_recent_document_for_user(self, user):
RecentDocument = apps.get_model(
app_label='documents', model_name='RecentDocument'
)
return RecentDocument.objects.add_document_for_user(user, self)
def delete(self, *args, **kwargs):
to_trash = kwargs.pop('to_trash', True)
if not self.in_trash and to_trash:
self.in_trash = True
self.deleted_date_time = now()
self.save()
else:
for version in self.versions.all():
version.delete()
return super(Document, self).delete(*args, **kwargs)
def exists(self):
"""
Returns a boolean value that indicates if the document's
latest version file exists in storage
"""
latest_version = self.latest_version
if latest_version:
return latest_version.exists()
else:
return False
def get_absolute_url(self):
return reverse(
viewname='documents:document_preview', kwargs={'pk': self.pk}
)
def get_api_image_url(self, *args, **kwargs):
latest_version = self.latest_version
if latest_version:
return latest_version.get_api_image_url(*args, **kwargs)
def invalidate_cache(self):
for document_version in self.versions.all():
document_version.invalidate_cache()
@property
def is_in_trash(self):
return self.in_trash
def natural_key(self):
return (self.uuid,)
natural_key.dependencies = ['documents.DocumentType']
def new_version(self, file_object, comment=None, _user=None):
logger.info('Creating new document version for document: %s', self)
DocumentVersion = apps.get_model(
app_label='documents', model_name='DocumentVersion'
)
document_version = DocumentVersion(
document=self, comment=comment or '', file=File(file_object)
)
document_version.save(_user=_user)
logger.info('New document version queued for document: %s', self)
return document_version
def open(self, *args, **kwargs):
"""
Return a file descriptor to a document's file irrespective of
the storage backend
"""
return self.latest_version.open(*args, **kwargs)
def restore(self):
self.in_trash = False
self.save()
def save(self, *args, **kwargs):
user = kwargs.pop('_user', None)
_commit_events = kwargs.pop('_commit_events', True)
new_document = not self.pk
super(Document, self).save(*args, **kwargs)
if new_document:
if user:
self.add_as_recent_document_for_user(user)
event_document_create.commit(
actor=user, target=self, action_object=self.document_type
)
else:
event_document_create.commit(
target=self, action_object=self.document_type
)
else:
if _commit_events:
event_document_properties_edit.commit(actor=user, target=self)
def save_to_file(self, *args, **kwargs):
return self.latest_version.save_to_file(*args, **kwargs)
def set_document_type(self, document_type, force=False, _user=None):
has_changed = self.document_type != document_type
self.document_type = document_type
self.save()
if has_changed or force:
post_document_type_change.send(
sender=self.__class__, instance=self
)
event_document_type_change.commit(actor=_user, target=self)
if _user:
self.add_as_recent_document_for_user(user=_user)
@property
def size(self):
return self.latest_version.size
# Compatibility methods
@property
def checksum(self):
return self.latest_version.checksum
@property
def date_updated(self):
return self.latest_version.timestamp
@property
def file_mime_encoding(self):
return self.latest_version.encoding
@property
def file_mimetype(self):
return self.latest_version.mimetype
@property
def latest_version(self):
return self.versions.order_by('timestamp').last()
@property
def page_count(self):
return self.latest_version.page_count
@property
def pages(self):
try:
return self.latest_version.pages
except AttributeError:
# Document has no version yet
DocumentPage = apps.get_model(
app_label='documents', model_name='DocumentPage'
)
return DocumentPage.objects.none()