Example #1
0
    def ready(self):
        super(DocumentCommentsApp, self).ready()

        Document = apps.get_model(
            app_label='documents', model_name='Document'
        )

        Comment = self.get_model('Comment')

        ModelEventType.register(
            model=Document, event_types=(
                event_document_comment_create, event_document_comment_delete
            )
        )

        ModelPermission.register(
            model=Document, permissions=(
                permission_comment_create, permission_comment_delete,
                permission_comment_view
            )
        )

        SourceColumn(source=Comment, label=_('Date'), attribute='submit_date')
        SourceColumn(
            source=Comment, label=_('User'),
            func=lambda context: context['object'].user.get_full_name() if context['object'].user.get_full_name() else context['object'].user
        )
        SourceColumn(source=Comment, label=_('Comment'), attribute='comment')

        document_page_search.add_model_field(
            field='document_version__document__comments__comment',
            label=_('Comments')
        )
        document_search.add_model_field(
            field='comments__comment',
            label=_('Comments')
        )

        menu_sidebar.bind_links(
            links=(link_comment_add,),
            sources=(
                'comments:comments_for_document', 'comments:comment_add',
                'comments:comment_delete', 'comments:comment_multiple_delete'
            )
        )
        menu_object.bind_links(
            links=(link_comment_delete,), sources=(Comment,)
        )
        menu_facet.bind_links(
            links=(link_comments_for_document,), sources=(Document,)
        )
Example #2
0
    def ready(self):
        super(DocumentParsingApp, self).ready()

        APIEndPoint(app=self, version_string='1')

        Document = apps.get_model(
            app_label='documents', model_name='Document'
        )

        DocumentVersion = apps.get_model(
            app_label='documents', model_name='DocumentVersion'
        )

        DocumentVersionParseError = self.get_model('DocumentVersionParseError')

        Document.add_to_class('submit_for_parsing', document_parsing_submit)
        DocumentVersion.add_to_class(
            'content', get_document_content
        )
        DocumentVersion.add_to_class(
            'submit_for_parsing', document_version_parsing_submit
        )

        ModelPermission.register(
            model=Document, permissions=(permission_content_view,)
        )

        SourceColumn(
            source=DocumentVersionParseError, label=_('Document'),
            func=lambda context: document_link(context['object'].document_version.document)
        )
        SourceColumn(
            source=DocumentVersionParseError, label=_('Added'),
            attribute='datetime_submitted'
        )
        SourceColumn(
            source=DocumentVersionParseError, label=_('Result'),
            attribute='result'
        )

        app.conf.CELERY_QUEUES.append(
            Queue('parsing', Exchange('parsing'), routing_key='parsing'),
        )

        app.conf.CELERY_ROUTES.update(
            {
                'document_parsing.tasks.task_parse_document_version': {
                    'queue': 'parsing'
                },
            }
        )

        document_search.add_model_field(
            field='versions__pages__content__content', label=_('Content')
        )

        document_page_search.add_model_field(
            field='content__content', label=_('Content')
        )

        menu_facet.bind_links(
            links=(link_document_content,), sources=(Document,)
        )
        menu_multi_item.bind_links(
            links=(link_document_submit_multiple,), sources=(Document,)
        )
        menu_object.bind_links(
            links=(link_document_submit,), sources=(Document,)
        )
        menu_secondary.bind_links(
            links=(
                link_document_content, link_document_parsing_errors_list,
                link_document_content_download
            ),
            sources=(
                'document_parsing:document_content',
                'document_parsing:document_content_download',
                'document_parsing:document_parsing_error_list',
            )
        )
        menu_tools.bind_links(
            links=(
                link_document_type_submit, link_error_list,
            )
        )

        post_version_upload.connect(
            dispatch_uid='document_parsing_handler_parse_document_version',
            receiver=handler_parse_document_version,
            sender=DocumentVersion
        )
Example #3
0
    def ready(self):
        super(TagsApp, self).ready()
        from actstream import registry

        from .wizard_steps import WizardStepTags  # NOQA

        Document = apps.get_model(
            app_label='documents', model_name='Document'
        )

        DocumentPageResult = apps.get_model(
            app_label='documents', model_name='DocumentPageResult'
        )

        DocumentTag = self.get_model('DocumentTag')
        Tag = self.get_model('Tag')

        Document.add_to_class(
            'attached_tags',
            lambda document: DocumentTag.objects.filter(documents=document)
        )

        ModelEventType.register(
            model=Tag, event_types=(
                event_tag_attach, event_tag_created, event_tag_edited,
                event_tag_remove
            )
        )

        ModelField(
            Document, name='tags__label'
        )
        ModelField(
            Document, name='tags__color'
        )

        ModelPermission.register(
            model=Document, permissions=(
                permission_tag_attach, permission_tag_remove,
                permission_tag_view
            )
        )

        ModelPermission.register(
            model=Tag, permissions=(
                permission_acl_edit, permission_acl_view,
                permission_events_view, permission_tag_attach,
                permission_tag_delete, permission_tag_edit,
                permission_tag_remove, permission_tag_view,
            )
        )

        SourceColumn(
            source=DocumentTag, attribute='label'
        )
        SourceColumn(
            source=DocumentTag, attribute='get_preview_widget'
        )

        SourceColumn(
            source=Document, label=_('Tags'),
            func=lambda context: widget_document_tags(
                document=context['object'], user=context['request'].user
            )
        )

        SourceColumn(
            source=DocumentPageResult, label=_('Tags'),
            func=lambda context: widget_document_tags(
                document=context['object'].document,
                user=context['request'].user
            )
        )

        SourceColumn(
            source=Tag, attribute='label'
        )
        SourceColumn(
            source=Tag, attribute='get_preview_widget'
        )
        SourceColumn(
            source=Tag, label=_('Documents'),
            func=lambda context: context['object'].get_document_count(
                user=context['request'].user
            )
        )

        document_page_search.add_model_field(
            field='document_version__document__tags__label', label=_('Tags')
        )
        document_search.add_model_field(field='tags__label', label=_('Tags'))

        menu_facet.bind_links(
            links=(link_tag_document_list,), sources=(Document,)
        )

        menu_tags.bind_links(
            links=(
                link_tag_list, link_tag_create
            )
        )

        menu_main.bind_links(links=(menu_tags,), position=98)

        menu_multi_item.bind_links(
            links=(
                link_multiple_documents_attach_tag,
                link_multiple_documents_tag_remove
            ),
            sources=(Document,)
        )
        menu_multi_item.bind_links(
            links=(link_tag_multiple_delete,), sources=(Tag,)
        )
        menu_object.bind_links(
            links=(
                link_tag_tagged_item_list, link_tag_edit, link_acl_list,
                link_events_for_object,
                link_object_event_types_user_subcriptions_list,
                link_tag_delete
            ),
            sources=(Tag,)
        )
        menu_sidebar.bind_links(
            links=(link_tag_attach, link_single_document_multiple_tag_remove),
            sources=(
                'tags:tag_attach', 'tags:document_tags',
                'tags:single_document_multiple_tag_remove'
            )
        )
        registry.register(Tag)

        # Index update

        m2m_changed.connect(
            handler_index_document,
            dispatch_uid='tags_handler_index_document',
            sender=Tag.documents.through
        )

        pre_delete.connect(
            handler_tag_pre_delete,
            dispatch_uid='tags_handler_tag_pre_delete',
            sender=Tag
        )
Example #4
0
    def ready(self):
        super(CabinetsApp, self).ready()
        from actstream import registry

        Document = apps.get_model(
            app_label='documents', model_name='Document'
        )

        DocumentCabinet = self.get_model('DocumentCabinet')
        Cabinet = self.get_model('Cabinet')

        APIEndPoint(app=self, version_string='1')

        # Add explicit order_by as DocumentCabinet ordering Meta option has no
        # effect.
        Document.add_to_class(
            'document_cabinets',
            lambda document: DocumentCabinet.objects.filter(documents=document).order_by('parent__label', 'label')
        )

        ModelPermission.register(
            model=Document, permissions=(
                permission_cabinet_add_document,
                permission_cabinet_remove_document
            )
        )

        ModelPermission.register(
            model=Cabinet, permissions=(
                permission_acl_edit, permission_acl_view,
                permission_cabinet_delete, permission_cabinet_edit,
                permission_cabinet_view, permission_cabinet_add_document,
                permission_cabinet_remove_document
            )
        )
        ModelPermission.register_inheritance(
            model=Cabinet, related='get_root',
        )

        SourceColumn(
            source=Document, label=_('Cabinets'),
            func=lambda context: widget_document_cabinets(
                document=context['object'], user=context['request'].user
            ), order=1
        )

        document_page_search.add_model_field(
            field='document_version__document__cabinets__label',
            label=_('Cabinets')
        )
        document_search.add_model_field(
            field='cabinets__label', label=_('Cabinets')
        )

        menu_facet.bind_links(
            links=(link_document_cabinet_list,), sources=(Document,)
        )

        menu_cabinets.bind_links(
            links=(
                link_cabinet_list, link_cabinet_create
            )
        )

        menu_main.bind_links(links=(menu_cabinets,), position=98)

        menu_multi_item.bind_links(
            links=(
                link_cabinet_add_multiple_documents,
                link_multiple_document_cabinet_remove
            ), sources=(Document,)
        )
        menu_object.bind_links(
            links=(
                link_cabinet_view,
            ), sources=(DocumentCabinet, )
        )
        menu_object.bind_links(
            links=(
                link_cabinet_view, link_cabinet_edit,
                link_custom_acl_list, link_cabinet_delete
            ), sources=(Cabinet,)
        )
        menu_sidebar.bind_links(
            links=(link_cabinet_child_add,), sources=(Cabinet,)
        )
        menu_sidebar.bind_links(
            links=(link_cabinet_add_document, link_document_cabinet_remove),
            sources=(
                'cabinets:document_cabinet_list',
                'cabinets:cabinet_add_document',
                'cabinets:document_cabinet_remove'
            )
        )

        registry.register(Cabinet)
Example #5
0
    def ready(self):
        super(TagsApp, self).ready()

        APIEndPoint(app=self, version_string='1')

        Document.add_to_class(
            'attached_tags',
            lambda document: DocumentTag.objects.filter(documents=document)
        )

        ModelPermission.register(
            model=Document, permissions=(
                permission_tag_attach, permission_tag_remove,
                permission_tag_view
            )
        )

        ModelPermission.register(
            model=Tag, permissions=(
                permission_acl_edit, permission_acl_view,
                permission_tag_delete, permission_tag_edit,
                permission_tag_view,
            )
        )

        SourceColumn(
            source=DocumentTag, label=_('Preview'),
            func=lambda context: widget_single_tag(context['object'])
        )

        SourceColumn(
            source=Document, label=_('Tags'),
            func=lambda context: widget_document_tags(
                document=context['object'], user=context['request'].user
            )
        )

        SourceColumn(
            source=Tag, label=_('Preview'),
            func=lambda context: widget_single_tag(context['object'])
        )
        SourceColumn(
            source=Tag, label=_('Documents'),
            func=lambda context: context['object'].get_document_count(
                user=context['request'].user
            )
        )

        document_search.add_model_field(field='tags__label', label=_('Tags'))

        menu_facet.bind_links(
            links=(link_tag_document_list,), sources=(Document,)
        )
        menu_main.bind_links(links=(link_tag_list,))
        menu_multi_item.bind_links(
            links=(
                link_multiple_documents_attach_tag,
                link_multiple_documents_tag_remove
            ),
            sources=(Document,)
        )
        menu_multi_item.bind_links(
            links=(link_tag_multiple_delete,), sources=(Tag,)
        )
        menu_multi_item.bind_links(
            links=(link_single_document_multiple_tag_remove,),
            sources=(DocumentTag,)
        )
        menu_object.bind_links(
            links=(
                link_tag_tagged_item_list, link_tag_edit, link_acl_list,
                link_tag_delete
            ),
            sources=(Tag,)
        )
        menu_secondary.bind_links(
            links=(link_tag_list, link_tag_create),
            sources=(Tag, 'tags:tag_list', 'tags:tag_create')
        )
        menu_sidebar.bind_links(
            links=(link_tag_attach,),
            sources=(
                'tags:document_tags', 'tags:tag_remove',
                'tags:tag_multiple_remove', 'tags:tag_attach'
            )
        )
Example #6
0
    def ready(self):
        super(OCRApp, self).ready()

        APIEndPoint(app=self, version_string='1')

        Document.add_to_class('submit_for_ocr', document_ocr_submit)
        DocumentVersion.add_to_class(
            'submit_for_ocr', document_version_ocr_submit
        )

        ModelPermission.register(
            model=Document, permissions=(
                permission_ocr_document, permission_ocr_content_view
            )
        )

        SourceColumn(
            source=DocumentVersionOCRError, label=_('Document'),
            func=lambda context: document_link(context['object'].document_version.document)
        )
        SourceColumn(
            source=DocumentVersionOCRError, label=_('Added'),
            attribute='datetime_submitted'
        )
        SourceColumn(
            source=DocumentVersionOCRError, label=_('Result'),
            attribute='result'
        )

        app.conf.CELERY_QUEUES.append(
            Queue('ocr', Exchange('ocr'), routing_key='ocr'),
        )

        app.conf.CELERY_ROUTES.update(
            {
                'ocr.tasks.task_do_ocr': {
                    'queue': 'ocr'
                },
            }
        )

        document_search.add_model_field(
            field='versions__pages__ocr_content__content', label=_('Content')
        )

        menu_facet.bind_links(
            links=(link_document_content,), sources=(Document,)
        )
        menu_multi_item.bind_links(
            links=(link_document_submit_multiple,), sources=(Document,)
        )
        menu_object.bind_links(
            links=(link_document_submit,), sources=(Document,)
        )
        menu_object.bind_links(
            links=(link_document_type_ocr_settings,), sources=(DocumentType,)
        )
        menu_secondary.bind_links(
            links=(link_entry_list,),
            sources=(
                'ocr:entry_list', 'ocr:entry_delete_multiple',
                'ocr:entry_re_queue_multiple', DocumentVersionOCRError
            )
        )
        menu_tools.bind_links(
            links=(
                link_document_submit_all, link_document_type_submit,
                link_entry_list
            )
        )

        post_save.connect(
            initialize_new_ocr_settings,
            dispatch_uid='initialize_new_ocr_settings', sender=DocumentType
        )
        post_version_upload.connect(
            post_version_upload_ocr, dispatch_uid='post_version_upload_ocr',
            sender=DocumentVersion
        )

        namespace = PropertyNamespace('ocr', _('OCR'))

        try:
            pdftotext = sh.Command(setting_pdftotext_path.value)
        except sh.CommandNotFound:
            namespace.add_property(
                'pdftotext', _('pdftotext version'), _('not found'),
                report=True
            )
        except Exception:
            namespace.add_property(
                'pdftotext', _('pdftotext version'),
                _('error getting version'), report=True
            )
        else:
            namespace.add_property(
                'pdftotext', _('pdftotext version'), pdftotext('-v').stderr,
                report=True
            )

        try:
            tesseract = sh.Command(setting_tesseract_path.value)
        except sh.CommandNotFound:
            namespace.add_property(
                'tesseract', _('tesseract version'), _('not found'),
                report=True
            )
        except Exception:
            namespace.add_property(
                'tesseract', _('tesseract version'),
                _('error getting version'), report=True
            )
        else:
            namespace.add_property(
                'tesseract', _('tesseract version'), tesseract('-v').stderr,
                report=True
            )
Example #7
0
    def ready(self):
        super(MetadataApp, self).ready()

        Document = apps.get_model(
            app_label='documents', model_name='Document'
        )
        DocumentPageResult = apps.get_model(
            app_label='documents', model_name='DocumentPageResult'
        )

        DocumentType = apps.get_model(
            app_label='documents', model_name='DocumentType'
        )

        DocumentMetadata = self.get_model('DocumentMetadata')
        DocumentTypeMetadataType = self.get_model('DocumentTypeMetadataType')
        MetadataType = self.get_model('MetadataType')

        APIEndPoint(app=self, version_string='2')

        Document.add_to_class(
            'metadata_value_of', DocumentMetadataHelper.constructor
        )

        Filter(
            label=_('Documents missing required metadata'),
            slug='documents-no-required-metadata',
            filter_kwargs=[
                {
                    'document_type__metadata__required': True,
                },
                {
                    'metadata__value__isnull': True
                },
                {
                    'is_stub': False
                }
            ], model=Document, object_permission=permission_document_view,
            hide_links=True
        )

        Filter(
            label=_('Documents missing optional metadata'),
            slug='documents-no-optional-metadata',
            filter_kwargs=[
                {
                    'document_type__metadata__required': False,
                },
                {
                    'metadata__value__isnull': True
                },
                {
                    'is_stub': False
                }
            ], model=Document, object_permission=permission_document_view,
            hide_links=True
        )

        ModelAttribute(
            Document, 'metadata', type_name='related',
            description=_(
                'Queryset containing a MetadataType instance reference and a '
                'value for that metadata type'
            )
        )
        ModelAttribute(
            Document, 'metadata__metadata_type__name',
            label=_('Metadata type name'), type_name='query'
        )
        ModelAttribute(
            Document, 'metadata__value', label=_('Metadata type value'),
            type_name='query'
        )
        ModelAttribute(
            Document, 'metadata_value_of', label=_('Value of a metadata'),
            description=_(
                'Return the value of a specific document metadata'
            ),
            type_name=['property', 'indexing']
        )

        ModelPermission.register(
            model=Document, permissions=(
                permission_metadata_document_add,
                permission_metadata_document_edit,
                permission_metadata_document_remove,
                permission_metadata_document_view,
            )
        )

        SourceColumn(
            source=Document, label=_('Metadata'),
            func=lambda context: get_metadata_string(context['object'])
        )

        SourceColumn(
            source=DocumentPageResult, label=_('Metadata'),
            func=lambda context: get_metadata_string(
                context['object'].document
            )
        )

        SourceColumn(
            source=DocumentMetadata, label=_('Value'),
            attribute='value'
        )
        SourceColumn(
            source=DocumentMetadata, label=_('Required'),
            func=lambda context: two_state_template(
                context['object'].is_required
            )
        )

        app.conf.CELERY_QUEUES.append(
            Queue('metadata', Exchange('metadata'), routing_key='metadata'),
        )

        app.conf.CELERY_ROUTES.update(
            {
                'metadata.tasks.task_remove_metadata_type': {
                    'queue': 'metadata'
                },
                'metadata.tasks.task_add_required_metadata_type': {
                    'queue': 'metadata'
                },
            }
        )

        document_search.add_model_field(
            field='metadata__metadata_type__name', label=_('Metadata type')
        )
        document_search.add_model_field(
            field='metadata__value', label=_('Metadata value')
        )

        document_page_search.add_model_field(
            field='document_version__document__metadata__metadata_type__name',
            label=_('Metadata type')
        )
        document_page_search.add_model_field(
            field='document_version__document__metadata__value',
            label=_('Metadata value')
        )

        menu_facet.bind_links(links=(link_metadata_view,), sources=(Document,))
        menu_multi_item.bind_links(
            links=(
                link_metadata_multiple_add, link_metadata_multiple_edit,
                link_metadata_multiple_remove
            ), sources=(Document,)
        )
        menu_object.bind_links(
            links=(
                link_setup_document_type_metadata_types,
            ), sources=(DocumentType,)
        )
        menu_object.bind_links(
            links=(
                link_setup_metadata_type_edit,
                link_setup_metadata_type_document_types,
                link_setup_metadata_type_delete
            ), sources=(MetadataType,)
        )
        menu_secondary.bind_links(
            links=(
                link_setup_metadata_type_list,
                link_setup_metadata_type_create
            ), sources=(
                MetadataType, 'metadata:setup_metadata_type_list',
                'metadata:setup_metadata_type_create'
            )
        )
        menu_setup.bind_links(links=(link_setup_metadata_type_list,))
        menu_sidebar.bind_links(
            links=(
                link_metadata_add, link_metadata_edit, link_metadata_remove
            ), sources=(
                'metadata:metadata_add', 'metadata:metadata_edit',
                'metadata:metadata_remove', 'metadata:metadata_view'
            )
        )

        post_delete.connect(
            post_document_type_metadata_type_delete,
            dispatch_uid='metadata_post_document_type_metadata_type_delete',
            sender=DocumentTypeMetadataType
        )
        post_document_type_change.connect(
            post_document_type_change_metadata,
            dispatch_uid='metadata_post_document_type_change_metadata',
            sender=Document
        )
        post_save.connect(
            post_document_type_metadata_type_add,
            dispatch_uid='metadata_post_document_type_metadata_type_add',
            sender=DocumentTypeMetadataType
        )

        # Index updating

        post_delete.connect(
            handler_index_document,
            dispatch_uid='metadata_handler_index_document_delete',
            sender=DocumentMetadata
        )
        post_save.connect(
            handler_index_document,
            dispatch_uid='metadata_handler_index_document_save',
            sender=DocumentMetadata
        )
Example #8
0
    def ready(self):
        super(OCRApp, self).ready()

        Document = apps.get_model(
            app_label='documents', model_name='Document'
        )
        DocumentPage = apps.get_model(
            app_label='documents', model_name='DocumentPage'
        )
        DocumentType = apps.get_model(
            app_label='documents', model_name='DocumentType'
        )
        DocumentTypeSettings = self.get_model(
            model_name='DocumentTypeSettings'
        )
        DocumentVersion = apps.get_model(
            app_label='documents', model_name='DocumentVersion'
        )

        DocumentVersionOCRError = self.get_model('DocumentVersionOCRError')

        Document.add_to_class('submit_for_ocr', document_ocr_submit)
        DocumentVersion.add_to_class(
            'ocr_content', get_document_ocr_content
        )
        DocumentVersion.add_to_class(
            'submit_for_ocr', document_version_ocr_submit
        )

        ModelField(
            Document, name='versions__pages__ocr_content__content'
        )

        ModelPermission.register(
            model=Document, permissions=(
                permission_ocr_document, permission_ocr_content_view
            )
        )
        ModelPermission.register(
            model=DocumentType, permissions=(
                permission_document_type_ocr_setup,
            )
        )
        ModelPermission.register_inheritance(
            model=DocumentTypeSettings, related='document_type',
        )

        SourceColumn(
            source=DocumentVersionOCRError, label=_('Document'),
            func=lambda context: document_link(context['object'].document_version.document)
        )
        SourceColumn(
            source=DocumentVersionOCRError, label=_('Added'),
            attribute='datetime_submitted'
        )
        SourceColumn(
            source=DocumentVersionOCRError, label=_('Result'),
            attribute='result'
        )

        app.conf.CELERY_QUEUES.append(
            Queue('ocr', Exchange('ocr'), routing_key='ocr'),
        )

        app.conf.CELERY_ROUTES.update(
            {
                'ocr.tasks.task_do_ocr': {
                    'queue': 'ocr'
                },
            }
        )

        document_search.add_model_field(
            field='versions__pages__ocr_content__content', label=_('OCR')
        )

        document_page_search.add_model_field(
            field='ocr_content__content', label=_('OCR')
        )

        menu_facet.bind_links(
            links=(link_document_ocr_content,), sources=(Document,)
        )
        menu_facet.bind_links(
            links=(link_document_page_ocr_content,), sources=(DocumentPage,)
        )
        menu_multi_item.bind_links(
            links=(link_document_submit_multiple,), sources=(Document,)
        )
        menu_object.bind_links(
            links=(link_document_submit,), sources=(Document,)
        )
        menu_object.bind_links(
            links=(link_document_page_ocr_content,), sources=(DocumentPage,)
        )
        menu_object.bind_links(
            links=(link_document_type_ocr_settings,), sources=(DocumentType,)
        )
        menu_secondary.bind_links(
            links=(
                link_document_ocr_content, link_document_ocr_errors_list,
                link_document_ocr_download
            ),
            sources=(
                'ocr:document_content', 'ocr:document_ocr_error_list',
                'ocr:document_ocr_download',
            )
        )
        menu_secondary.bind_links(
            links=(link_entry_list,),
            sources=(
                'ocr:entry_list', 'ocr:entry_delete_multiple',
                'ocr:entry_re_queue_multiple', DocumentVersionOCRError
            )
        )
        menu_tools.bind_links(
            links=(
                link_document_type_submit, link_entry_list
            )
        )

        post_document_version_ocr.connect(
            dispatch_uid='ocr_handler_index_document',
            receiver=handler_index_document,
            sender=DocumentVersion
        )
        post_save.connect(
            dispatch_uid='ocr_handler_initialize_new_ocr_settings',
            receiver=handler_initialize_new_ocr_settings,
            sender=DocumentType
        )
        post_version_upload.connect(
            dispatch_uid='ocr_handler_ocr_document_version',
            receiver=handler_ocr_document_version,
            sender=DocumentVersion
        )
Example #9
0
    def ready(self):
        super(TagsApp, self).ready()
        from actstream import registry

        Document = apps.get_model(
            app_label='documents', model_name='Document'
        )

        DocumentPageResult = apps.get_model(
            app_label='documents', model_name='DocumentPageResult'
        )

        DocumentTag = self.get_model('DocumentTag')
        Tag = self.get_model('Tag')

        APIEndPoint(app=self, version_string='1')

        Document.add_to_class(
            'attached_tags',
            lambda document: DocumentTag.objects.filter(documents=document)
        )

        ModelPermission.register(
            model=Document, permissions=(
                permission_tag_attach, permission_tag_remove,
                permission_tag_view
            )
        )

        ModelPermission.register(
            model=Tag, permissions=(
                permission_acl_edit, permission_acl_view,
                permission_tag_attach, permission_tag_delete,
                permission_tag_edit, permission_tag_remove,
                permission_tag_view
            )
        )

        SourceColumn(
            source=DocumentTag, label=_('Preview'),
            func=lambda context: widget_single_tag(context['object'])
        )

        SourceColumn(
            source=Document, label=_('Tags'),
            func=lambda context: widget_document_tags(
                document=context['object'], user=context['request'].user
            )
        )

        SourceColumn(
            source=DocumentPageResult, label=_('Tags'),
            func=lambda context: widget_document_tags(
                document=context['object'].document,
                user=context['request'].user
            )
        )

        SourceColumn(
            source=Tag, label=_('Preview'),
            func=lambda context: widget_single_tag(context['object'])
        )
        SourceColumn(
            source=Tag, label=_('Documents'),
            func=lambda context: context['object'].get_document_count(
                user=context['request'].user
            )
        )

        document_page_search.add_model_field(
            field='document_version__document__tags__label', label=_('Tags')
        )
        document_search.add_model_field(field='tags__label', label=_('Tags'))

        menu_facet.bind_links(
            links=(link_tag_document_list,), sources=(Document,)
        )

        menu_tags.bind_links(
            links=(
                link_tag_list, link_tag_create
            )
        )

        menu_main.bind_links(links=(menu_tags,), position=98)

        menu_multi_item.bind_links(
            links=(
                link_multiple_documents_attach_tag,
                link_multiple_documents_tag_remove
            ),
            sources=(Document,)
        )
        menu_multi_item.bind_links(
            links=(link_tag_multiple_delete,), sources=(Tag,)
        )
        menu_object.bind_links(
            links=(
                link_tag_tagged_item_list, link_tag_edit, link_acl_list,
                link_tag_delete
            ),
            sources=(Tag,)
        )
        menu_sidebar.bind_links(
            links=(link_tag_attach, link_single_document_multiple_tag_remove),
            sources=(
                'tags:tag_attach', 'tags:document_tags',
                'tags:single_document_multiple_tag_remove'
            )
        )
        registry.register(Tag)