class LayerTransformation(models.Model): """ Model that stores the transformation and transformation arguments for a given object Fields: * order - Order of a Transformation - In case there are multiple transformations for an object, this field list the order at which they will be execute. * arguments - Arguments of a Transformation - An optional field to hold a transformation argument. Example: if a page is rotated with the Rotation transformation, this field will show by how many degrees it was rotated. """ object_layer = models.ForeignKey(on_delete=models.CASCADE, related_name='transformations', to=ObjectLayer, verbose_name=_('Object layer')) order = models.PositiveIntegerField( blank=True, db_index=True, default=0, help_text=_( 'Order in which the transformations will be executed. If left ' 'unchanged, an automatic order value will be assigned.'), verbose_name=_('Order')) name = models.CharField(max_length=128, verbose_name=_('Name')) arguments = models.TextField( blank=True, help_text=_('Enter the arguments for the transformation as a YAML ' 'dictionary. ie: {"degrees": 180}'), validators=[YAMLValidator()], verbose_name=_('Arguments')) enabled = models.BooleanField(default=True, verbose_name=_('Enabled')) objects = LayerTransformationManager() class Meta: ordering = ( 'object_layer__stored_layer__order', 'order', ) unique_together = ('object_layer', 'order') verbose_name = _('Layer transformation') verbose_name_plural = _('Layer transformations') def __str__(self): try: return str(BaseTransformation.get(name=self.name)) except KeyError: return ugettext('Unknown transformation class') def get_transformation_class(self): return BaseTransformation.get(name=self.name) def save(self, *args, **kwargs): if not self.order: self.order = self.object_layer.get_next_order() super(LayerTransformation, self).save(*args, **kwargs)
class WorkflowTransitionField(models.Model): transition = models.ForeignKey( on_delete=models.CASCADE, related_name='fields', to=WorkflowTransition, verbose_name=_('Transition') ) field_type = models.PositiveIntegerField( choices=FIELD_TYPE_CHOICES, verbose_name=_('Type') ) name = models.CharField( help_text=_( 'The name that will be used to identify this field in other parts ' 'of the workflow system.' ), max_length=128, verbose_name=_('Internal name') ) label = models.CharField( help_text=_( 'The field name that will be shown on the user interface.' ), max_length=128, verbose_name=_('Label')) help_text = models.TextField( blank=True, help_text=_( 'An optional message that will help users better understand the ' 'purpose of the field and data to provide.' ), verbose_name=_('Help text') ) required = models.BooleanField( default=False, help_text=_( 'Whether this fields needs to be filled out or not to proceed.' ), verbose_name=_('Required') ) widget = models.PositiveIntegerField( blank=True, choices=WIDGET_CLASS_CHOICES, help_text=_( 'An optional class to change the default presentation of the field.' ), null=True, verbose_name=_('Widget class') ) widget_kwargs = models.TextField( blank=True, help_text=_( 'A group of keyword arguments to customize the widget. ' 'Use YAML format.' ), validators=[YAMLValidator()], verbose_name=_('Widget keyword arguments') ) class Meta: unique_together = ('transition', 'name') verbose_name = _('Workflow transition field') verbose_name_plural = _('Workflow transition fields') def __str__(self): return self.label def get_widget_kwargs(self): return yaml_load(stream=self.widget_kwargs)
class DocumentType(models.Model): """ Define document types or classes to which a specific set of properties can be attached """ label = models.CharField(help_text=_('The name of the document type.'), max_length=96, unique=True, verbose_name=_('Label')) trash_time_period = models.PositiveIntegerField( blank=True, help_text=_( 'Amount of time after which documents of this type will be ' 'moved to the trash.'), null=True, verbose_name=_('Trash time period')) trash_time_unit = models.CharField(blank=True, choices=TIME_DELTA_UNIT_CHOICES, null=True, max_length=8, verbose_name=_('Trash time unit')) delete_time_period = models.PositiveIntegerField( blank=True, default=DEFAULT_DELETE_PERIOD, help_text=_( 'Amount of time after which documents of this type in the trash ' 'will be deleted.'), null=True, verbose_name=_('Delete time period')) delete_time_unit = models.CharField(blank=True, choices=TIME_DELTA_UNIT_CHOICES, default=DEFAULT_DELETE_TIME_UNIT, max_length=8, null=True, verbose_name=_('Delete time unit')) filename_generator_backend = models.CharField( default=BaseDocumentFilenameGenerator.get_default(), help_text=_( 'The class responsible for producing the actual filename used ' 'to store the uploaded documents.'), max_length=224, verbose_name=_('Filename generator backend')) filename_generator_backend_arguments = models.TextField( blank=True, help_text=_('The arguments for the filename generator backend as a ' 'YAML dictionary.'), validators=[YAMLValidator()], verbose_name=_('Filename generator backend arguments')) objects = DocumentTypeManager() class Meta: ordering = ('label', ) verbose_name = _('Document type') verbose_name_plural = _('Documents types') def __str__(self): return self.label def delete(self, *args, **kwargs): Document = apps.get_model(app_label='documents', model_name='Document') for document in Document.objects.filter(document_type=self): document.delete(to_trash=False) return super(DocumentType, self).delete(*args, **kwargs) @property def deleted_documents(self): DeletedDocument = apps.get_model(app_label='documents', model_name='DeletedDocument') return DeletedDocument.objects.filter(document_type=self) def get_absolute_url(self): return reverse(viewname='documents:document_type_document_list', kwargs={'document_type_id': self.pk}) def get_document_count(self, user): queryset = AccessControlList.objects.restrict_queryset( permission=permission_document_view, queryset=self.documents, user=user) return queryset.count() def get_upload_filename(self, instance, filename): generator_klass = BaseDocumentFilenameGenerator.get( name=self.filename_generator_backend) generator_instance = generator_klass(**yaml_load( stream=self.filename_generator_backend_arguments or '{}')) return generator_instance.upload_to(instance=instance, filename=filename) def natural_key(self): return (self.label, ) def new_document(self, file_object, label=None, description=None, language=None, _user=None): Document = apps.get_model(app_label='documents', model_name='Document') try: document = Document(description=description or '', document_type=self, label=label or file_object.name, language=language or setting_language.value) document.save(_user=_user) except Exception as exception: logger.critical( 'Unexpected exception while trying to create new document ' '"%s" from document type "%s"; %s', label or file_object.name, self, exception) raise else: try: document.new_version(file_object=file_object, _user=_user) except Exception as exception: logger.critical( 'Unexpected exception while trying to create initial ' 'version for document %s; %s', label or file_object.name, exception) raise else: return document def save(self, *args, **kwargs): user = kwargs.pop('_user', None) created = not self.pk result = super(DocumentType, self).save(*args, **kwargs) if created: event_document_type_created.commit(actor=user, target=self) else: event_document_type_edited.commit(actor=user, target=self) return result