Merge branch 'feature/indexing_refactor' into development

This commit is contained in:
Roberto Rosario
2012-02-02 10:45:11 -04:00
27 changed files with 1396 additions and 232 deletions

View File

@@ -8,17 +8,43 @@ from navigation.api import register_top_menu, register_sidebar_template, \
from main.api import register_maintenance_links
from documents.permissions import PERMISSION_DOCUMENT_VIEW
from documents.models import Document
from project_setup.api import register_setup
from .models import IndexInstance
from .models import (Index, IndexTemplateNode, IndexInstanceNode)
from .permissions import (PERMISSION_DOCUMENT_INDEXING_VIEW,
PERMISSION_DOCUMENT_INDEXING_REBUILD_INDEXES)
PERMISSION_DOCUMENT_INDEXING_REBUILD_INDEXES,
PERMISSION_DOCUMENT_INDEXING_SETUP,
PERMISSION_DOCUMENT_INDEXING_CREATE,
PERMISSION_DOCUMENT_INDEXING_EDIT,
PERMISSION_DOCUMENT_INDEXING_DELETE
)
index_list = {'text': _(u'index list'), 'view': 'index_instance_list', 'famfam': 'folder_page', 'permissions': [PERMISSION_DOCUMENT_INDEXING_VIEW]}
index_parent = {'text': _(u'go up one level'), 'view': 'index_instance_list', 'args': 'object.parent.pk', 'famfam': 'arrow_up', 'permissions': [PERMISSION_DOCUMENT_INDEXING_VIEW], 'dont_mark_active': True}
def is_root_node(context):
return context['node'].parent is None
def is_not_instance_root_node(context):
return context['object'].parent is not None
index_setup = {'text': _(u'indexes'), 'view': 'index_setup_list', 'icon': 'tab.png', 'permissions': [PERMISSION_DOCUMENT_INDEXING_SETUP]}
index_setup_list = {'text': _(u'index list'), 'view': 'index_setup_list', 'famfam': 'tab', 'permissions': [PERMISSION_DOCUMENT_INDEXING_SETUP]}
index_setup_create = {'text': _(u'create index'), 'view': 'index_setup_create', 'famfam': 'tab_add', 'permissions': [PERMISSION_DOCUMENT_INDEXING_CREATE]}
index_setup_edit = {'text': _(u'edit'), 'view': 'index_setup_edit', 'args': 'index.pk', 'famfam': 'tab_edit', 'permissions': [PERMISSION_DOCUMENT_INDEXING_EDIT]}
index_setup_delete = {'text': _(u'delete'), 'view': 'index_setup_delete', 'args': 'index.pk', 'famfam': 'tab_delete', 'permissions': [PERMISSION_DOCUMENT_INDEXING_DELETE]}
index_setup_view = {'text': _(u'tree template'), 'view': 'index_setup_view', 'args': 'index.pk', 'famfam': 'textfield', 'permissions': [PERMISSION_DOCUMENT_INDEXING_SETUP]}
template_node_create = {'text': _(u'new child node'), 'view': 'template_node_create', 'args': 'node.pk', 'famfam': 'textfield_add', 'permissions': [PERMISSION_DOCUMENT_INDEXING_SETUP]}
template_node_edit = {'text': _(u'edit'), 'view': 'template_node_edit', 'args': 'node.pk', 'famfam': 'textfield', 'permissions': [PERMISSION_DOCUMENT_INDEXING_SETUP], 'conditional_disable': is_root_node}
template_node_delete = {'text': _(u'delete'), 'view': 'template_node_delete', 'args': 'node.pk', 'famfam': 'textfield_delete', 'permissions': [PERMISSION_DOCUMENT_INDEXING_SETUP], 'conditional_disable': is_root_node}
index_list = {'text': _(u'index list'), 'view': 'index_list', 'famfam': 'folder_page', 'permissions': [PERMISSION_DOCUMENT_INDEXING_VIEW]}
index_parent = {'text': _(u'go up one level'), 'view': 'index_instance_node_view', 'args': 'object.parent.pk', 'famfam': 'arrow_up', 'permissions': [PERMISSION_DOCUMENT_INDEXING_VIEW], 'dont_mark_active': True, 'condition': is_not_instance_root_node}
document_index_list = {'text': _(u'indexes'), 'view': 'document_index_list', 'args': 'object.pk', 'famfam': 'folder_page', 'permissions': [PERMISSION_DOCUMENT_INDEXING_VIEW, PERMISSION_DOCUMENT_VIEW]}
register_top_menu('indexes', link={'text': _('indexes'), 'famfam': 'folder_page', 'view': 'index_instance_list'})
register_top_menu('indexes', link={'text': _('indexes'), 'famfam': 'folder_page', 'view': 'index_list'})
rebuild_index_instances = {'text': _('rebuild indexes'), 'view': 'rebuild_index_instances', 'famfam': 'folder_page', 'permissions': [PERMISSION_DOCUMENT_INDEXING_REBUILD_INDEXES], 'description': _(u'Deletes and creates from scratch all the document indexes.')}
@@ -26,6 +52,14 @@ register_maintenance_links([rebuild_index_instances], namespace='document_indexi
register_sidebar_template(['index_instance_list'], 'indexing_help.html')
register_links(IndexInstance, [index_parent])
register_links(IndexInstanceNode, [index_parent])
register_links(Document, [document_index_list], menu_name='form_header')
register_setup(index_setup)
register_links([Index, 'index_setup_list', 'index_setup_create', 'template_node_edit', 'template_node_delete'], [index_setup_list, index_setup_create], menu_name='secondary_menu')
register_links(Index, [index_setup_edit, index_setup_delete, index_setup_view])
register_links(IndexTemplateNode, [template_node_create, template_node_edit, template_node_delete])

View File

@@ -1,27 +1,23 @@
from __future__ import absolute_import
from django.contrib import admin
from mptt.admin import MPTTModelAdmin
from document_indexing.models import Index, IndexInstance, \
DocumentRenameCount
from .models import (Index, IndexTemplateNode, IndexInstanceNode,
DocumentRenameCount)
class IndexInstanceInline(admin.StackedInline):
model = IndexInstance
extra = 1
classes = ('collapse-open',)
allow_add = True
class IndexAdmin(MPTTModelAdmin):
class IndexTemplateNodeAdmin(MPTTModelAdmin):
list_display = ('expression', 'enabled', 'link_documents')
class IndexInstanceAdmin(MPTTModelAdmin):
model = IndexInstance
list_display = ('value', 'index', 'get_document_list_display')
class IndexInstanceNodeAdmin(MPTTModelAdmin):
model = IndexInstanceNode
list_display = ('value',)
admin.site.register(Index, IndexAdmin)
admin.site.register(IndexInstance, IndexInstanceAdmin)
admin.site.register(Index)
admin.site.register(IndexTemplateNode, IndexTemplateNodeAdmin)
admin.site.register(IndexInstanceNode, IndexInstanceNodeAdmin)
admin.site.register(DocumentRenameCount)

View File

@@ -3,19 +3,18 @@ from __future__ import absolute_import
from django.utils.translation import ugettext_lazy as _
from django.utils.translation import ugettext
from django.core.urlresolvers import reverse
from django.utils.safestring import mark_safe
from django.template.defaultfilters import slugify
from documents.models import Document
from metadata.classes import MetadataObject
from metadata.classes import MetadataClass
from .models import (Index, IndexInstance, DocumentRenameCount)
from .models import (Index, IndexTemplateNode, IndexInstanceNode,
DocumentRenameCount)
from .conf.settings import (AVAILABLE_INDEXING_FUNCTIONS,
MAX_SUFFIX_COUNT, SLUGIFY_PATHS)
from .filesystem import (fs_create_index_directory,
fs_create_document_link, fs_delete_document_link,
fs_delete_index_directory, fs_delete_directory_recusive)
from .os_specifics import assemble_suffixed_filename
fs_delete_index_directory, assemble_suffixed_filename)
from .exceptions import MaxSuffixCountReached
if SLUGIFY_PATHS == False:
# Do not slugify path or filenames and extensions
@@ -24,10 +23,6 @@ else:
SLUGIFY_FUNCTION = slugify
class MaxSuffixCountReached(Exception):
pass
# External functions
def update_indexes(document):
"""
@@ -38,11 +33,13 @@ def update_indexes(document):
eval_dict = {}
document_metadata_dict = dict([(metadata.metadata_type.name, metadata.value) for metadata in document.documentmetadata_set.all() if metadata.value])
eval_dict['document'] = document
eval_dict['metadata'] = MetadataObject(document_metadata_dict)
eval_dict['metadata'] = MetadataClass(document_metadata_dict)
for root in Index.objects.filter(parent=None):
index_warnings = _evaluate_index(eval_dict, document, root)
warnings.extend(index_warnings)
for index in Index.objects.filter(enabled=True):
root_instance, created = IndexInstanceNode.objects.get_or_create(index_template_node=index.template_root, parent=None)
for template_node in index.template_root.get_children():
index_warnings = cascade_eval(eval_dict, document, template_node, root_instance)
warnings.extend(index_warnings)
return warnings
@@ -53,136 +50,80 @@ def delete_indexes(document):
"""
warnings = []
for index_instance in document.indexinstance_set.all():
index_warnings = _remove_document_from_index_instance(document, index_instance)
for index_instance in document.indexinstancenode_set.all():
index_warnings = cascade_document_remove(document, index_instance)
warnings.extend(index_warnings)
return warnings
def get_instance_link(index_instance=None, text=None, simple=False):
"""
Return an HTML anchor to an index instance
"""
if simple:
# Just display the instance's value or overrided text, no
# HTML anchor
template = u'%(value)s'
else:
template = u'<a href="%(url)s">%(value)s</a>'
if index_instance:
return template % {
'url': index_instance.get_absolute_url(),
'value': text if text else index_instance
}
else:
# Root node
return template % {
'url': reverse('index_instance_list'),
'value': ugettext(u'root')
}
def get_breadcrumbs(index_instance, simple=False, single_link=False, include_count=False):
"""
Return a joined string of HTML anchors to every index instance's
parent from the root of the tree to the index instance
"""
result = []
if single_link:
# Return the entire breadcrumb path as a single HTML anchor
simple = True
result.append(get_instance_link(simple=simple))
for instance in index_instance.get_ancestors():
result.append(get_instance_link(instance, simple=simple))
result.append(get_instance_link(index_instance, simple=simple))
output = []
if include_count:
output.append(u'(%d)' % index_instance.documents.count())
if single_link:
# Return the entire breadcrumb path as a single HTML anchor
output.insert(0, get_instance_link(index_instance=index_instance, text=(u' / '.join(result))))
return mark_safe(u' '.join(output))
else:
output.insert(0, u' / '.join(result))
return mark_safe(u' '.join(output))
def do_rebuild_all_indexes():
fs_delete_directory_recusive()
IndexInstance.objects.all().delete()
DocumentRenameCount.objects.all().delete()
for document in Document.objects.all():
update_indexes(document)
return [] # Warnings - None
# Internal functions
def find_lowest_available_suffix(index_instance, document):
# TODO: verify extension's role in query
index_instance_documents = DocumentRenameCount.objects.filter(index_instance=index_instance)#.filter(document__file_extension=document.file_extension)
index_instance_documents = DocumentRenameCount.objects.filter(index_instance_node=index_instance)
files_list = []
for index_instance_document in index_instance_documents:
files_list.append(assemble_suffixed_filename(index_instance_document.document.file.name, index_instance_document.suffix))
files_list.append(assemble_suffixed_filename(index_instance_document.document.file_filename, index_instance_document.suffix))
for suffix in xrange(MAX_SUFFIX_COUNT):
if assemble_suffixed_filename(document.file.name, suffix) not in files_list:
if assemble_suffixed_filename(document.file_filename, suffix) not in files_list:
return suffix
raise MaxSuffixCountReached(ugettext(u'Maximum suffix (%s) count reached.') % MAX_SUFFIX_COUNT)
def _evaluate_index(eval_dict, document, node, parent_index_instance=None):
def cascade_eval(eval_dict, document, template_node, parent_index_instance=None):
"""
Evaluate an enabled index expression and update or create all the
related index instances also recursively calling itself to evaluate
all the index's children
"""
warnings = []
if node.enabled:
if template_node.enabled:
try:
result = eval(node.expression, eval_dict, AVAILABLE_INDEXING_FUNCTIONS)
result = eval(template_node.expression, eval_dict, AVAILABLE_INDEXING_FUNCTIONS)
except (NameError, AttributeError), exc:
warnings.append(_(u'Error in document indexing update expression: %(expression)s; %(exception)s') % {
'expression': template_node.expression, 'exception': exc})
else:
if result:
index_instance, created = IndexInstance.objects.get_or_create(index=node, value=result, parent=parent_index_instance)
index_instance, created = IndexInstanceNode.objects.get_or_create(index_template_node=template_node)
index_instance.value = result
index_instance.parent = parent_index_instance
index_instance.save()
#if created:
fs_create_index_directory(index_instance)
if node.link_documents:
try:
fs_create_index_directory(index_instance)
except Exception, exc:
warnings.append(_(u'Error updating document index, expression: %(expression)s; %(exception)s') % {
'expression': template_node.expression, 'exception': exc})
if template_node.link_documents:
suffix = find_lowest_available_suffix(index_instance, document)
document_count = DocumentRenameCount(
index_instance=index_instance,
index_instance_node=index_instance,
document=document,
suffix=suffix
)
document_count.save()
fs_create_document_link(index_instance, document, suffix)
try:
fs_create_document_link(index_instance, document, suffix)
except Exception, exc:
warnings.append(_(u'Error updating document index, expression: %(expression)s; %(exception)s') % {
'expression': template_node.expression, 'exception': exc})
index_instance.documents.add(document)
for children in node.get_children():
children_warnings = _evaluate_index(
eval_dict, document, children, index_instance
for child in template_node.get_children():
children_warnings = cascade_eval(
eval_dict, document, child, index_instance
)
warnings.extend(children_warnings)
except (NameError, AttributeError), exc:
warnings.append(_(u'Error in document indexing update expression: %(expression)s; %(exception)s') % {
'expression': node.expression, 'exception': exc})
except Exception, exc:
warnings.append(_(u'Error updating document index, expression: %(expression)s; %(exception)s') % {
'expression': node.expression, 'exception': exc})
return warnings
def _remove_document_from_index_instance(document, index_instance):
def cascade_document_remove(document, index_instance):
"""
Delete a documents reference from an index instance and call itself
recusively deleting documents and empty index instances up to the
@@ -190,7 +131,7 @@ def _remove_document_from_index_instance(document, index_instance):
"""
warnings = []
try:
document_rename_count = DocumentRenameCount.objects.get(index_instance=index_instance, document=document)
document_rename_count = DocumentRenameCount.objects.get(index_instance_node=index_instance, document=document)
fs_delete_document_link(index_instance, document, document_rename_count.suffix)
document_rename_count.delete()
index_instance.documents.remove(document)
@@ -200,7 +141,7 @@ def _remove_document_from_index_instance(document, index_instance):
parent = index_instance.parent
fs_delete_index_directory(index_instance)
index_instance.delete()
parent_warnings = _remove_document_from_index_instance(
parent_warnings = cascade_document_remove(
document, parent
)
warnings.extend(parent_warnings)

View File

@@ -1,5 +1,7 @@
"""Configuration options for the document_indexing app"""
from django.utils.translation import ugettext_lazy as _
from common.utils import proper_name
from smart_settings.api import register_settings
@@ -17,7 +19,6 @@ register_settings(
# Filesystem serving
{'name': u'SLUGIFY_PATHS', 'global_name': u'DOCUMENT_INDEXING_FILESYSTEM_SLUGIFY_PATHS', 'default': False},
{'name': u'MAX_SUFFIX_COUNT', 'global_name': u'DOCUMENT_INDEXING_FILESYSTEM_MAX_SUFFIX_COUNT', 'default': 1000},
{'name': u'FILESERVING_PATH', 'global_name': u'DOCUMENT_INDEXING_FILESYSTEM_FILESERVING_PATH', 'default': u'/tmp/mayan/documents', 'exists': True},
{'name': u'FILESERVING_ENABLE', 'global_name': u'DOCUMENT_INDEXING_FILESYSTEM_FILESERVING_ENABLE', 'default': True}
{'name': u'FILESYSTEM_SERVING', 'global_name': u'DOCUMENT_INDEXING_FILESYSTEM_SERVING', 'default': {}, 'description': _(u'A dictionary that maps the index name and where on the filesystem that index will be mirrored.')}
]
)

View File

@@ -0,0 +1,6 @@
class MaxSuffixCountReached(Exception):
"""
Raised when there are too many documents with the same filename in the
same node/directory
"""
pass

View File

@@ -5,9 +5,24 @@ import os
from django.utils.translation import ugettext_lazy as _
from .os_specifics import (assemble_suffixed_filename,
assemble_path_from_list)
from .conf.settings import (FILESERVING_ENABLE, FILESERVING_PATH)
from .conf.settings import (FILESYSTEM_SERVING, SUFFIX_SEPARATOR)
def assemble_suffixed_filename(filename, suffix=0):
"""
Split document filename, to attach suffix to the name part then
re attacht the extension
"""
if suffix:
name, extension = os.path.splitext(filename)
return SUFFIX_SEPARATOR.join([name, unicode(suffix), os.extsep, extension])
else:
return filename
def assemble_path_from_list(directory_list):
return os.sep.join(directory_list)
def get_instance_path(index_instance):
@@ -25,8 +40,8 @@ def get_instance_path(index_instance):
def fs_create_index_directory(index_instance):
if FILESERVING_ENABLE:
target_directory = assemble_path_from_list([FILESERVING_PATH, get_instance_path(index_instance)])
if index_instance.index_template_node.index.name in FILESYSTEM_SERVING:
target_directory = assemble_path_from_list([FILESYSTEM_SERVING[index_instance.index_template_node.index.name], get_instance_path(index_instance)])
try:
os.mkdir(target_directory)
except OSError, exc:
@@ -37,9 +52,9 @@ def fs_create_index_directory(index_instance):
def fs_create_document_link(index_instance, document, suffix=0):
if FILESERVING_ENABLE:
filename = assemble_suffixed_filename(document.file.name, suffix)
filepath = assemble_path_from_list([FILESERVING_PATH, get_instance_path(index_instance), filename])
if index_instance.index_template_node.index.name in FILESYSTEM_SERVING:
filename = assemble_suffixed_filename(document.file_filename, suffix)
filepath = assemble_path_from_list([FILESYSTEM_SERVING[index_instance.index_template_node.index.name], get_instance_path(index_instance), filename])
try:
os.symlink(document.file.path, filepath)
@@ -57,9 +72,9 @@ def fs_create_document_link(index_instance, document, suffix=0):
def fs_delete_document_link(index_instance, document, suffix=0):
if FILESERVING_ENABLE:
filename = assemble_suffixed_filename(document.file.name, suffix)
filepath = assemble_path_from_list([FILESERVING_PATH, get_instance_path(index_instance), filename])
if index_instance.index_template_node.index.name in FILESYSTEM_SERVING:
filename = assemble_suffixed_filename(document.file_filename, suffix)
filepath = assemble_path_from_list([FILESYSTEM_SERVING[index_instance.index_template_node.index.name], get_instance_path(index_instance), filename])
try:
os.unlink(filepath)
@@ -70,8 +85,8 @@ def fs_delete_document_link(index_instance, document, suffix=0):
def fs_delete_index_directory(index_instance):
if FILESERVING_ENABLE:
target_directory = assemble_path_from_list([FILESERVING_PATH, get_instance_path(index_instance)])
if index_instance.index_template_node.index.name in FILESYSTEM_SERVING:
target_directory = assemble_path_from_list([FILESYSTEM_SERVING[index_instance.index_template_node.index.name], get_instance_path(index_instance)])
try:
os.removedirs(target_directory)
except OSError, exc:
@@ -81,8 +96,9 @@ def fs_delete_index_directory(index_instance):
raise Exception(_(u'Unable to delete indexing directory; %s') % exc)
def fs_delete_directory_recusive(path=FILESERVING_PATH):
if FILESERVING_ENABLE:
def fs_delete_directory_recusive(index):
if index.name in FILESYSTEM_SERVING:
path = FILESYSTEM_SERVING[index.name]
for dirpath, dirnames, filenames in os.walk(path, topdown=False):
for filename in filenames:
os.unlink(os.path.join(dirpath, filename))

View File

@@ -0,0 +1,27 @@
from __future__ import absolute_import
from django import forms
from django.utils.translation import ugettext_lazy as _
from .models import Index, IndexTemplateNode
class IndexForm(forms.ModelForm):
"""
A standard model form to allow users to create a new index
"""
class Meta:
model = Index
class IndexTemplateNodeForm(forms.ModelForm):
"""
A standard model form to allow users to create a new index template node
"""
def __init__(self, *args, **kwargs):
super(IndexTemplateNodeForm, self).__init__(*args, **kwargs)
self.fields['index'].widget = forms.widgets.HiddenInput()
self.fields['parent'].widget = forms.widgets.HiddenInput()
class Meta:
model = IndexTemplateNode

View File

@@ -0,0 +1,189 @@
# encoding: utf-8
import datetime
from south.db import db
from south.v2 import SchemaMigration
from django.db import models
class Migration(SchemaMigration):
def forwards(self, orm):
# Adding model 'Index'
db.create_table('document_indexing_index', (
('id', self.gf('django.db.models.fields.AutoField')(primary_key=True)),
('parent', self.gf('mptt.fields.TreeForeignKey')(blank=True, related_name='index_meta_class', null=True, to=orm['document_indexing.Index'])),
('expression', self.gf('django.db.models.fields.CharField')(max_length=128)),
('enabled', self.gf('django.db.models.fields.BooleanField')(default=True)),
('link_documents', self.gf('django.db.models.fields.BooleanField')(default=False)),
('lft', self.gf('django.db.models.fields.PositiveIntegerField')(db_index=True)),
('rght', self.gf('django.db.models.fields.PositiveIntegerField')(db_index=True)),
('tree_id', self.gf('django.db.models.fields.PositiveIntegerField')(db_index=True)),
('level', self.gf('django.db.models.fields.PositiveIntegerField')(db_index=True)),
))
db.send_create_signal('document_indexing', ['Index'])
# Adding model 'IndexInstance'
db.create_table('document_indexing_indexinstance', (
('id', self.gf('django.db.models.fields.AutoField')(primary_key=True)),
('parent', self.gf('mptt.fields.TreeForeignKey')(blank=True, related_name='index_meta_instance', null=True, to=orm['document_indexing.IndexInstance'])),
('index', self.gf('django.db.models.fields.related.ForeignKey')(to=orm['document_indexing.Index'])),
('value', self.gf('django.db.models.fields.CharField')(max_length=128, blank=True)),
('lft', self.gf('django.db.models.fields.PositiveIntegerField')(db_index=True)),
('rght', self.gf('django.db.models.fields.PositiveIntegerField')(db_index=True)),
('tree_id', self.gf('django.db.models.fields.PositiveIntegerField')(db_index=True)),
('level', self.gf('django.db.models.fields.PositiveIntegerField')(db_index=True)),
))
db.send_create_signal('document_indexing', ['IndexInstance'])
# Adding M2M table for field documents on 'IndexInstance'
db.create_table('document_indexing_indexinstance_documents', (
('id', models.AutoField(verbose_name='ID', primary_key=True, auto_created=True)),
('indexinstance', models.ForeignKey(orm['document_indexing.indexinstance'], null=False)),
('document', models.ForeignKey(orm['documents.document'], null=False))
))
db.create_unique('document_indexing_indexinstance_documents', ['indexinstance_id', 'document_id'])
# Adding model 'DocumentRenameCount'
db.create_table('document_indexing_documentrenamecount', (
('id', self.gf('django.db.models.fields.AutoField')(primary_key=True)),
('index_instance', self.gf('django.db.models.fields.related.ForeignKey')(to=orm['document_indexing.IndexInstance'])),
('document', self.gf('django.db.models.fields.related.ForeignKey')(to=orm['documents.Document'])),
('suffix', self.gf('django.db.models.fields.PositiveIntegerField')(blank=True)),
))
db.send_create_signal('document_indexing', ['DocumentRenameCount'])
def backwards(self, orm):
# Deleting model 'Index'
db.delete_table('document_indexing_index')
# Deleting model 'IndexInstance'
db.delete_table('document_indexing_indexinstance')
# Removing M2M table for field documents on 'IndexInstance'
db.delete_table('document_indexing_indexinstance_documents')
# Deleting model 'DocumentRenameCount'
db.delete_table('document_indexing_documentrenamecount')
models = {
'auth.group': {
'Meta': {'object_name': 'Group'},
'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}),
'name': ('django.db.models.fields.CharField', [], {'unique': 'True', 'max_length': '80'}),
'permissions': ('django.db.models.fields.related.ManyToManyField', [], {'to': "orm['auth.Permission']", 'symmetrical': 'False', 'blank': 'True'})
},
'auth.permission': {
'Meta': {'ordering': "('content_type__app_label', 'content_type__model', 'codename')", 'unique_together': "(('content_type', 'codename'),)", 'object_name': 'Permission'},
'codename': ('django.db.models.fields.CharField', [], {'max_length': '100'}),
'content_type': ('django.db.models.fields.related.ForeignKey', [], {'to': "orm['contenttypes.ContentType']"}),
'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}),
'name': ('django.db.models.fields.CharField', [], {'max_length': '50'})
},
'auth.user': {
'Meta': {'object_name': 'User'},
'date_joined': ('django.db.models.fields.DateTimeField', [], {'default': 'datetime.datetime.now'}),
'email': ('django.db.models.fields.EmailField', [], {'max_length': '75', 'blank': 'True'}),
'first_name': ('django.db.models.fields.CharField', [], {'max_length': '30', 'blank': 'True'}),
'groups': ('django.db.models.fields.related.ManyToManyField', [], {'to': "orm['auth.Group']", 'symmetrical': 'False', 'blank': 'True'}),
'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}),
'is_active': ('django.db.models.fields.BooleanField', [], {'default': 'True'}),
'is_staff': ('django.db.models.fields.BooleanField', [], {'default': 'False'}),
'is_superuser': ('django.db.models.fields.BooleanField', [], {'default': 'False'}),
'last_login': ('django.db.models.fields.DateTimeField', [], {'default': 'datetime.datetime.now'}),
'last_name': ('django.db.models.fields.CharField', [], {'max_length': '30', 'blank': 'True'}),
'password': ('django.db.models.fields.CharField', [], {'max_length': '128'}),
'user_permissions': ('django.db.models.fields.related.ManyToManyField', [], {'to': "orm['auth.Permission']", 'symmetrical': 'False', 'blank': 'True'}),
'username': ('django.db.models.fields.CharField', [], {'unique': 'True', 'max_length': '30'})
},
'comments.comment': {
'Meta': {'ordering': "('submit_date',)", 'object_name': 'Comment', 'db_table': "'django_comments'"},
'comment': ('django.db.models.fields.TextField', [], {'max_length': '3000'}),
'content_type': ('django.db.models.fields.related.ForeignKey', [], {'related_name': "'content_type_set_for_comment'", 'to': "orm['contenttypes.ContentType']"}),
'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}),
'ip_address': ('django.db.models.fields.IPAddressField', [], {'max_length': '15', 'null': 'True', 'blank': 'True'}),
'is_public': ('django.db.models.fields.BooleanField', [], {'default': 'True'}),
'is_removed': ('django.db.models.fields.BooleanField', [], {'default': 'False'}),
'object_pk': ('django.db.models.fields.TextField', [], {}),
'site': ('django.db.models.fields.related.ForeignKey', [], {'to': "orm['sites.Site']"}),
'submit_date': ('django.db.models.fields.DateTimeField', [], {'default': 'None'}),
'user': ('django.db.models.fields.related.ForeignKey', [], {'blank': 'True', 'related_name': "'comment_comments'", 'null': 'True', 'to': "orm['auth.User']"}),
'user_email': ('django.db.models.fields.EmailField', [], {'max_length': '75', 'blank': 'True'}),
'user_name': ('django.db.models.fields.CharField', [], {'max_length': '50', 'blank': 'True'}),
'user_url': ('django.db.models.fields.URLField', [], {'max_length': '200', 'blank': 'True'})
},
'contenttypes.contenttype': {
'Meta': {'ordering': "('name',)", 'unique_together': "(('app_label', 'model'),)", 'object_name': 'ContentType', 'db_table': "'django_content_type'"},
'app_label': ('django.db.models.fields.CharField', [], {'max_length': '100'}),
'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}),
'model': ('django.db.models.fields.CharField', [], {'max_length': '100'}),
'name': ('django.db.models.fields.CharField', [], {'max_length': '100'})
},
'document_indexing.documentrenamecount': {
'Meta': {'object_name': 'DocumentRenameCount'},
'document': ('django.db.models.fields.related.ForeignKey', [], {'to': "orm['documents.Document']"}),
'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}),
'index_instance': ('django.db.models.fields.related.ForeignKey', [], {'to': "orm['document_indexing.IndexInstance']"}),
'suffix': ('django.db.models.fields.PositiveIntegerField', [], {'blank': 'True'})
},
'document_indexing.index': {
'Meta': {'object_name': 'Index'},
'enabled': ('django.db.models.fields.BooleanField', [], {'default': 'True'}),
'expression': ('django.db.models.fields.CharField', [], {'max_length': '128'}),
'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}),
'level': ('django.db.models.fields.PositiveIntegerField', [], {'db_index': 'True'}),
'lft': ('django.db.models.fields.PositiveIntegerField', [], {'db_index': 'True'}),
'link_documents': ('django.db.models.fields.BooleanField', [], {'default': 'False'}),
'parent': ('mptt.fields.TreeForeignKey', [], {'blank': 'True', 'related_name': "'index_meta_class'", 'null': 'True', 'to': "orm['document_indexing.Index']"}),
'rght': ('django.db.models.fields.PositiveIntegerField', [], {'db_index': 'True'}),
'tree_id': ('django.db.models.fields.PositiveIntegerField', [], {'db_index': 'True'})
},
'document_indexing.indexinstance': {
'Meta': {'object_name': 'IndexInstance'},
'documents': ('django.db.models.fields.related.ManyToManyField', [], {'to': "orm['documents.Document']", 'symmetrical': 'False'}),
'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}),
'index': ('django.db.models.fields.related.ForeignKey', [], {'to': "orm['document_indexing.Index']"}),
'level': ('django.db.models.fields.PositiveIntegerField', [], {'db_index': 'True'}),
'lft': ('django.db.models.fields.PositiveIntegerField', [], {'db_index': 'True'}),
'parent': ('mptt.fields.TreeForeignKey', [], {'blank': 'True', 'related_name': "'index_meta_instance'", 'null': 'True', 'to': "orm['document_indexing.IndexInstance']"}),
'rght': ('django.db.models.fields.PositiveIntegerField', [], {'db_index': 'True'}),
'tree_id': ('django.db.models.fields.PositiveIntegerField', [], {'db_index': 'True'}),
'value': ('django.db.models.fields.CharField', [], {'max_length': '128', 'blank': 'True'})
},
'documents.document': {
'Meta': {'ordering': "['-date_added']", 'object_name': 'Document'},
'date_added': ('django.db.models.fields.DateTimeField', [], {'db_index': 'True'}),
'description': ('django.db.models.fields.TextField', [], {'null': 'True', 'blank': 'True'}),
'document_type': ('django.db.models.fields.related.ForeignKey', [], {'to': "orm['documents.DocumentType']", 'null': 'True', 'blank': 'True'}),
'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}),
'uuid': ('django.db.models.fields.CharField', [], {'max_length': '48', 'blank': 'True'})
},
'documents.documenttype': {
'Meta': {'ordering': "['name']", 'object_name': 'DocumentType'},
'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}),
'name': ('django.db.models.fields.CharField', [], {'max_length': '32'})
},
'sites.site': {
'Meta': {'ordering': "('domain',)", 'object_name': 'Site', 'db_table': "'django_site'"},
'domain': ('django.db.models.fields.CharField', [], {'max_length': '100'}),
'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}),
'name': ('django.db.models.fields.CharField', [], {'max_length': '50'})
},
'taggit.tag': {
'Meta': {'object_name': 'Tag'},
'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}),
'name': ('django.db.models.fields.CharField', [], {'max_length': '100'}),
'slug': ('django.db.models.fields.SlugField', [], {'unique': 'True', 'max_length': '100', 'db_index': 'True'})
},
'taggit.taggeditem': {
'Meta': {'object_name': 'TaggedItem'},
'content_type': ('django.db.models.fields.related.ForeignKey', [], {'related_name': "'taggit_taggeditem_tagged_items'", 'to': "orm['contenttypes.ContentType']"}),
'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}),
'object_id': ('django.db.models.fields.IntegerField', [], {'db_index': 'True'}),
'tag': ('django.db.models.fields.related.ForeignKey', [], {'related_name': "'taggit_taggeditem_items'", 'to': "orm['taggit.Tag']"})
}
}
complete_apps = ['document_indexing']

View File

@@ -0,0 +1,75 @@
# encoding: utf-8
import datetime
from south.db import db
from south.v2 import SchemaMigration
from django.db import models
class Migration(SchemaMigration):
def forwards(self, orm):
# Deleting model 'DocumentRenameCount'
db.delete_table('document_indexing_documentrenamecount')
# Deleting model 'IndexInstance'
db.delete_table('document_indexing_indexinstance')
# Removing M2M table for field documents on 'IndexInstance'
db.delete_table('document_indexing_indexinstance_documents')
# Deleting model 'Index'
db.delete_table('document_indexing_index')
def backwards(self, orm):
# Adding model 'DocumentRenameCount'
db.create_table('document_indexing_documentrenamecount', (
('suffix', self.gf('django.db.models.fields.PositiveIntegerField')(blank=True)),
('index_instance', self.gf('django.db.models.fields.related.ForeignKey')(to=orm['document_indexing.IndexInstance'])),
('document', self.gf('django.db.models.fields.related.ForeignKey')(to=orm['documents.Document'])),
('id', self.gf('django.db.models.fields.AutoField')(primary_key=True)),
))
db.send_create_signal('document_indexing', ['DocumentRenameCount'])
# Adding model 'IndexInstance'
db.create_table('document_indexing_indexinstance', (
('index', self.gf('django.db.models.fields.related.ForeignKey')(to=orm['document_indexing.Index'])),
('parent', self.gf('mptt.fields.TreeForeignKey')(related_name='index_meta_instance', null=True, to=orm['document_indexing.IndexInstance'], blank=True)),
('level', self.gf('django.db.models.fields.PositiveIntegerField')(db_index=True)),
('lft', self.gf('django.db.models.fields.PositiveIntegerField')(db_index=True)),
('tree_id', self.gf('django.db.models.fields.PositiveIntegerField')(db_index=True)),
('rght', self.gf('django.db.models.fields.PositiveIntegerField')(db_index=True)),
('value', self.gf('django.db.models.fields.CharField')(max_length=128, blank=True)),
('id', self.gf('django.db.models.fields.AutoField')(primary_key=True)),
))
db.send_create_signal('document_indexing', ['IndexInstance'])
# Adding M2M table for field documents on 'IndexInstance'
db.create_table('document_indexing_indexinstance_documents', (
('id', models.AutoField(verbose_name='ID', primary_key=True, auto_created=True)),
('indexinstance', models.ForeignKey(orm['document_indexing.indexinstance'], null=False)),
('document', models.ForeignKey(orm['documents.document'], null=False))
))
db.create_unique('document_indexing_indexinstance_documents', ['indexinstance_id', 'document_id'])
# Adding model 'Index'
db.create_table('document_indexing_index', (
('lft', self.gf('django.db.models.fields.PositiveIntegerField')(db_index=True)),
('parent', self.gf('mptt.fields.TreeForeignKey')(related_name='index_meta_class', null=True, to=orm['document_indexing.Index'], blank=True)),
('level', self.gf('django.db.models.fields.PositiveIntegerField')(db_index=True)),
('link_documents', self.gf('django.db.models.fields.BooleanField')(default=False)),
('expression', self.gf('django.db.models.fields.CharField')(max_length=128)),
('tree_id', self.gf('django.db.models.fields.PositiveIntegerField')(db_index=True)),
('enabled', self.gf('django.db.models.fields.BooleanField')(default=True)),
('id', self.gf('django.db.models.fields.AutoField')(primary_key=True)),
('rght', self.gf('django.db.models.fields.PositiveIntegerField')(db_index=True)),
))
db.send_create_signal('document_indexing', ['Index'])
models = {
}
complete_apps = ['document_indexing']

View File

@@ -0,0 +1,191 @@
# encoding: utf-8
import datetime
from south.db import db
from south.v2 import SchemaMigration
from django.db import models
class Migration(SchemaMigration):
def forwards(self, orm):
# Adding model 'IndexTemplateNode'
db.create_table('document_indexing_indextemplatenode', (
('id', self.gf('django.db.models.fields.AutoField')(primary_key=True)),
('parent', self.gf('mptt.fields.TreeForeignKey')(blank=True, related_name='index_template_node', null=True, to=orm['document_indexing.IndexTemplateNode'])),
('index', self.gf('django.db.models.fields.related.ForeignKey')(to=orm['document_indexing.Index'])),
('expression', self.gf('django.db.models.fields.CharField')(max_length=128)),
('enabled', self.gf('django.db.models.fields.BooleanField')(default=True)),
('link_documents', self.gf('django.db.models.fields.BooleanField')(default=False)),
('lft', self.gf('django.db.models.fields.PositiveIntegerField')(db_index=True)),
('rght', self.gf('django.db.models.fields.PositiveIntegerField')(db_index=True)),
('tree_id', self.gf('django.db.models.fields.PositiveIntegerField')(db_index=True)),
('level', self.gf('django.db.models.fields.PositiveIntegerField')(db_index=True)),
))
db.send_create_signal('document_indexing', ['IndexTemplateNode'])
# Adding model 'IndexInstanceNode'
db.create_table('document_indexing_indexinstancenode', (
('id', self.gf('django.db.models.fields.AutoField')(primary_key=True)),
('parent', self.gf('mptt.fields.TreeForeignKey')(blank=True, related_name='index_instance_node', null=True, to=orm['document_indexing.IndexInstanceNode'])),
('index_template_node', self.gf('django.db.models.fields.related.ForeignKey')(to=orm['document_indexing.IndexTemplateNode'])),
('value', self.gf('django.db.models.fields.CharField')(max_length=128, blank=True)),
('lft', self.gf('django.db.models.fields.PositiveIntegerField')(db_index=True)),
('rght', self.gf('django.db.models.fields.PositiveIntegerField')(db_index=True)),
('tree_id', self.gf('django.db.models.fields.PositiveIntegerField')(db_index=True)),
('level', self.gf('django.db.models.fields.PositiveIntegerField')(db_index=True)),
))
db.send_create_signal('document_indexing', ['IndexInstanceNode'])
# Adding M2M table for field documents on 'IndexInstanceNode'
db.create_table('document_indexing_indexinstancenode_documents', (
('id', models.AutoField(verbose_name='ID', primary_key=True, auto_created=True)),
('indexinstancenode', models.ForeignKey(orm['document_indexing.indexinstancenode'], null=False)),
('document', models.ForeignKey(orm['documents.document'], null=False))
))
db.create_unique('document_indexing_indexinstancenode_documents', ['indexinstancenode_id', 'document_id'])
# Adding model 'Index'
db.create_table('document_indexing_index', (
('id', self.gf('django.db.models.fields.AutoField')(primary_key=True)),
('name', self.gf('django.db.models.fields.CharField')(max_length=64)),
('title', self.gf('django.db.models.fields.CharField')(max_length=128)),
('enabled', self.gf('django.db.models.fields.BooleanField')(default=True)),
))
db.send_create_signal('document_indexing', ['Index'])
def backwards(self, orm):
# Deleting model 'IndexTemplateNode'
db.delete_table('document_indexing_indextemplatenode')
# Deleting model 'IndexInstanceNode'
db.delete_table('document_indexing_indexinstancenode')
# Removing M2M table for field documents on 'IndexInstanceNode'
db.delete_table('document_indexing_indexinstancenode_documents')
# Deleting model 'Index'
db.delete_table('document_indexing_index')
models = {
'auth.group': {
'Meta': {'object_name': 'Group'},
'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}),
'name': ('django.db.models.fields.CharField', [], {'unique': 'True', 'max_length': '80'}),
'permissions': ('django.db.models.fields.related.ManyToManyField', [], {'to': "orm['auth.Permission']", 'symmetrical': 'False', 'blank': 'True'})
},
'auth.permission': {
'Meta': {'ordering': "('content_type__app_label', 'content_type__model', 'codename')", 'unique_together': "(('content_type', 'codename'),)", 'object_name': 'Permission'},
'codename': ('django.db.models.fields.CharField', [], {'max_length': '100'}),
'content_type': ('django.db.models.fields.related.ForeignKey', [], {'to': "orm['contenttypes.ContentType']"}),
'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}),
'name': ('django.db.models.fields.CharField', [], {'max_length': '50'})
},
'auth.user': {
'Meta': {'object_name': 'User'},
'date_joined': ('django.db.models.fields.DateTimeField', [], {'default': 'datetime.datetime.now'}),
'email': ('django.db.models.fields.EmailField', [], {'max_length': '75', 'blank': 'True'}),
'first_name': ('django.db.models.fields.CharField', [], {'max_length': '30', 'blank': 'True'}),
'groups': ('django.db.models.fields.related.ManyToManyField', [], {'to': "orm['auth.Group']", 'symmetrical': 'False', 'blank': 'True'}),
'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}),
'is_active': ('django.db.models.fields.BooleanField', [], {'default': 'True'}),
'is_staff': ('django.db.models.fields.BooleanField', [], {'default': 'False'}),
'is_superuser': ('django.db.models.fields.BooleanField', [], {'default': 'False'}),
'last_login': ('django.db.models.fields.DateTimeField', [], {'default': 'datetime.datetime.now'}),
'last_name': ('django.db.models.fields.CharField', [], {'max_length': '30', 'blank': 'True'}),
'password': ('django.db.models.fields.CharField', [], {'max_length': '128'}),
'user_permissions': ('django.db.models.fields.related.ManyToManyField', [], {'to': "orm['auth.Permission']", 'symmetrical': 'False', 'blank': 'True'}),
'username': ('django.db.models.fields.CharField', [], {'unique': 'True', 'max_length': '30'})
},
'comments.comment': {
'Meta': {'ordering': "('submit_date',)", 'object_name': 'Comment', 'db_table': "'django_comments'"},
'comment': ('django.db.models.fields.TextField', [], {'max_length': '3000'}),
'content_type': ('django.db.models.fields.related.ForeignKey', [], {'related_name': "'content_type_set_for_comment'", 'to': "orm['contenttypes.ContentType']"}),
'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}),
'ip_address': ('django.db.models.fields.IPAddressField', [], {'max_length': '15', 'null': 'True', 'blank': 'True'}),
'is_public': ('django.db.models.fields.BooleanField', [], {'default': 'True'}),
'is_removed': ('django.db.models.fields.BooleanField', [], {'default': 'False'}),
'object_pk': ('django.db.models.fields.TextField', [], {}),
'site': ('django.db.models.fields.related.ForeignKey', [], {'to': "orm['sites.Site']"}),
'submit_date': ('django.db.models.fields.DateTimeField', [], {'default': 'None'}),
'user': ('django.db.models.fields.related.ForeignKey', [], {'blank': 'True', 'related_name': "'comment_comments'", 'null': 'True', 'to': "orm['auth.User']"}),
'user_email': ('django.db.models.fields.EmailField', [], {'max_length': '75', 'blank': 'True'}),
'user_name': ('django.db.models.fields.CharField', [], {'max_length': '50', 'blank': 'True'}),
'user_url': ('django.db.models.fields.URLField', [], {'max_length': '200', 'blank': 'True'})
},
'contenttypes.contenttype': {
'Meta': {'ordering': "('name',)", 'unique_together': "(('app_label', 'model'),)", 'object_name': 'ContentType', 'db_table': "'django_content_type'"},
'app_label': ('django.db.models.fields.CharField', [], {'max_length': '100'}),
'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}),
'model': ('django.db.models.fields.CharField', [], {'max_length': '100'}),
'name': ('django.db.models.fields.CharField', [], {'max_length': '100'})
},
'document_indexing.index': {
'Meta': {'object_name': 'Index'},
'enabled': ('django.db.models.fields.BooleanField', [], {'default': 'True'}),
'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}),
'name': ('django.db.models.fields.CharField', [], {'max_length': '64'}),
'title': ('django.db.models.fields.CharField', [], {'max_length': '128'})
},
'document_indexing.indexinstancenode': {
'Meta': {'object_name': 'IndexInstanceNode'},
'documents': ('django.db.models.fields.related.ManyToManyField', [], {'to': "orm['documents.Document']", 'symmetrical': 'False'}),
'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}),
'index_template_node': ('django.db.models.fields.related.ForeignKey', [], {'to': "orm['document_indexing.IndexTemplateNode']"}),
'level': ('django.db.models.fields.PositiveIntegerField', [], {'db_index': 'True'}),
'lft': ('django.db.models.fields.PositiveIntegerField', [], {'db_index': 'True'}),
'parent': ('mptt.fields.TreeForeignKey', [], {'blank': 'True', 'related_name': "'index_instance_node'", 'null': 'True', 'to': "orm['document_indexing.IndexInstanceNode']"}),
'rght': ('django.db.models.fields.PositiveIntegerField', [], {'db_index': 'True'}),
'tree_id': ('django.db.models.fields.PositiveIntegerField', [], {'db_index': 'True'}),
'value': ('django.db.models.fields.CharField', [], {'max_length': '128', 'blank': 'True'})
},
'document_indexing.indextemplatenode': {
'Meta': {'object_name': 'IndexTemplateNode'},
'enabled': ('django.db.models.fields.BooleanField', [], {'default': 'True'}),
'expression': ('django.db.models.fields.CharField', [], {'max_length': '128'}),
'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}),
'index': ('django.db.models.fields.related.ForeignKey', [], {'to': "orm['document_indexing.Index']"}),
'level': ('django.db.models.fields.PositiveIntegerField', [], {'db_index': 'True'}),
'lft': ('django.db.models.fields.PositiveIntegerField', [], {'db_index': 'True'}),
'link_documents': ('django.db.models.fields.BooleanField', [], {'default': 'False'}),
'parent': ('mptt.fields.TreeForeignKey', [], {'blank': 'True', 'related_name': "'index_template_node'", 'null': 'True', 'to': "orm['document_indexing.IndexTemplateNode']"}),
'rght': ('django.db.models.fields.PositiveIntegerField', [], {'db_index': 'True'}),
'tree_id': ('django.db.models.fields.PositiveIntegerField', [], {'db_index': 'True'})
},
'documents.document': {
'Meta': {'ordering': "['-date_added']", 'object_name': 'Document'},
'date_added': ('django.db.models.fields.DateTimeField', [], {'db_index': 'True'}),
'description': ('django.db.models.fields.TextField', [], {'null': 'True', 'blank': 'True'}),
'document_type': ('django.db.models.fields.related.ForeignKey', [], {'to': "orm['documents.DocumentType']", 'null': 'True', 'blank': 'True'}),
'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}),
'uuid': ('django.db.models.fields.CharField', [], {'max_length': '48', 'blank': 'True'})
},
'documents.documenttype': {
'Meta': {'ordering': "['name']", 'object_name': 'DocumentType'},
'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}),
'name': ('django.db.models.fields.CharField', [], {'max_length': '32'})
},
'sites.site': {
'Meta': {'ordering': "('domain',)", 'object_name': 'Site', 'db_table': "'django_site'"},
'domain': ('django.db.models.fields.CharField', [], {'max_length': '100'}),
'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}),
'name': ('django.db.models.fields.CharField', [], {'max_length': '50'})
},
'taggit.tag': {
'Meta': {'object_name': 'Tag'},
'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}),
'name': ('django.db.models.fields.CharField', [], {'max_length': '100'}),
'slug': ('django.db.models.fields.SlugField', [], {'unique': 'True', 'max_length': '100', 'db_index': 'True'})
},
'taggit.taggeditem': {
'Meta': {'object_name': 'TaggedItem'},
'content_type': ('django.db.models.fields.related.ForeignKey', [], {'related_name': "'taggit_taggeditem_tagged_items'", 'to': "orm['contenttypes.ContentType']"}),
'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}),
'object_id': ('django.db.models.fields.IntegerField', [], {'db_index': 'True'}),
'tag': ('django.db.models.fields.related.ForeignKey', [], {'related_name': "'taggit_taggeditem_items'", 'to': "orm['taggit.Tag']"})
}
}
complete_apps = ['document_indexing']

View File

@@ -0,0 +1,153 @@
# encoding: utf-8
import datetime
from south.db import db
from south.v2 import SchemaMigration
from django.db import models
class Migration(SchemaMigration):
def forwards(self, orm):
# Adding model 'DocumentRenameCount'
db.create_table('document_indexing_documentrenamecount', (
('id', self.gf('django.db.models.fields.AutoField')(primary_key=True)),
('index_instance_node', self.gf('django.db.models.fields.related.ForeignKey')(to=orm['document_indexing.IndexInstanceNode'])),
('document', self.gf('django.db.models.fields.related.ForeignKey')(to=orm['documents.Document'])),
('suffix', self.gf('django.db.models.fields.PositiveIntegerField')(blank=True)),
))
db.send_create_signal('document_indexing', ['DocumentRenameCount'])
def backwards(self, orm):
# Deleting model 'DocumentRenameCount'
db.delete_table('document_indexing_documentrenamecount')
models = {
'auth.group': {
'Meta': {'object_name': 'Group'},
'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}),
'name': ('django.db.models.fields.CharField', [], {'unique': 'True', 'max_length': '80'}),
'permissions': ('django.db.models.fields.related.ManyToManyField', [], {'to': "orm['auth.Permission']", 'symmetrical': 'False', 'blank': 'True'})
},
'auth.permission': {
'Meta': {'ordering': "('content_type__app_label', 'content_type__model', 'codename')", 'unique_together': "(('content_type', 'codename'),)", 'object_name': 'Permission'},
'codename': ('django.db.models.fields.CharField', [], {'max_length': '100'}),
'content_type': ('django.db.models.fields.related.ForeignKey', [], {'to': "orm['contenttypes.ContentType']"}),
'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}),
'name': ('django.db.models.fields.CharField', [], {'max_length': '50'})
},
'auth.user': {
'Meta': {'object_name': 'User'},
'date_joined': ('django.db.models.fields.DateTimeField', [], {'default': 'datetime.datetime.now'}),
'email': ('django.db.models.fields.EmailField', [], {'max_length': '75', 'blank': 'True'}),
'first_name': ('django.db.models.fields.CharField', [], {'max_length': '30', 'blank': 'True'}),
'groups': ('django.db.models.fields.related.ManyToManyField', [], {'to': "orm['auth.Group']", 'symmetrical': 'False', 'blank': 'True'}),
'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}),
'is_active': ('django.db.models.fields.BooleanField', [], {'default': 'True'}),
'is_staff': ('django.db.models.fields.BooleanField', [], {'default': 'False'}),
'is_superuser': ('django.db.models.fields.BooleanField', [], {'default': 'False'}),
'last_login': ('django.db.models.fields.DateTimeField', [], {'default': 'datetime.datetime.now'}),
'last_name': ('django.db.models.fields.CharField', [], {'max_length': '30', 'blank': 'True'}),
'password': ('django.db.models.fields.CharField', [], {'max_length': '128'}),
'user_permissions': ('django.db.models.fields.related.ManyToManyField', [], {'to': "orm['auth.Permission']", 'symmetrical': 'False', 'blank': 'True'}),
'username': ('django.db.models.fields.CharField', [], {'unique': 'True', 'max_length': '30'})
},
'comments.comment': {
'Meta': {'ordering': "('submit_date',)", 'object_name': 'Comment', 'db_table': "'django_comments'"},
'comment': ('django.db.models.fields.TextField', [], {'max_length': '3000'}),
'content_type': ('django.db.models.fields.related.ForeignKey', [], {'related_name': "'content_type_set_for_comment'", 'to': "orm['contenttypes.ContentType']"}),
'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}),
'ip_address': ('django.db.models.fields.IPAddressField', [], {'max_length': '15', 'null': 'True', 'blank': 'True'}),
'is_public': ('django.db.models.fields.BooleanField', [], {'default': 'True'}),
'is_removed': ('django.db.models.fields.BooleanField', [], {'default': 'False'}),
'object_pk': ('django.db.models.fields.TextField', [], {}),
'site': ('django.db.models.fields.related.ForeignKey', [], {'to': "orm['sites.Site']"}),
'submit_date': ('django.db.models.fields.DateTimeField', [], {'default': 'None'}),
'user': ('django.db.models.fields.related.ForeignKey', [], {'blank': 'True', 'related_name': "'comment_comments'", 'null': 'True', 'to': "orm['auth.User']"}),
'user_email': ('django.db.models.fields.EmailField', [], {'max_length': '75', 'blank': 'True'}),
'user_name': ('django.db.models.fields.CharField', [], {'max_length': '50', 'blank': 'True'}),
'user_url': ('django.db.models.fields.URLField', [], {'max_length': '200', 'blank': 'True'})
},
'contenttypes.contenttype': {
'Meta': {'ordering': "('name',)", 'unique_together': "(('app_label', 'model'),)", 'object_name': 'ContentType', 'db_table': "'django_content_type'"},
'app_label': ('django.db.models.fields.CharField', [], {'max_length': '100'}),
'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}),
'model': ('django.db.models.fields.CharField', [], {'max_length': '100'}),
'name': ('django.db.models.fields.CharField', [], {'max_length': '100'})
},
'document_indexing.documentrenamecount': {
'Meta': {'object_name': 'DocumentRenameCount'},
'document': ('django.db.models.fields.related.ForeignKey', [], {'to': "orm['documents.Document']"}),
'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}),
'index_instance_node': ('django.db.models.fields.related.ForeignKey', [], {'to': "orm['document_indexing.IndexInstanceNode']"}),
'suffix': ('django.db.models.fields.PositiveIntegerField', [], {'blank': 'True'})
},
'document_indexing.index': {
'Meta': {'object_name': 'Index'},
'enabled': ('django.db.models.fields.BooleanField', [], {'default': 'True'}),
'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}),
'name': ('django.db.models.fields.CharField', [], {'max_length': '64'}),
'title': ('django.db.models.fields.CharField', [], {'max_length': '128'})
},
'document_indexing.indexinstancenode': {
'Meta': {'object_name': 'IndexInstanceNode'},
'documents': ('django.db.models.fields.related.ManyToManyField', [], {'to': "orm['documents.Document']", 'symmetrical': 'False'}),
'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}),
'index_template_node': ('django.db.models.fields.related.ForeignKey', [], {'to': "orm['document_indexing.IndexTemplateNode']"}),
'level': ('django.db.models.fields.PositiveIntegerField', [], {'db_index': 'True'}),
'lft': ('django.db.models.fields.PositiveIntegerField', [], {'db_index': 'True'}),
'parent': ('mptt.fields.TreeForeignKey', [], {'blank': 'True', 'related_name': "'index_instance_node'", 'null': 'True', 'to': "orm['document_indexing.IndexInstanceNode']"}),
'rght': ('django.db.models.fields.PositiveIntegerField', [], {'db_index': 'True'}),
'tree_id': ('django.db.models.fields.PositiveIntegerField', [], {'db_index': 'True'}),
'value': ('django.db.models.fields.CharField', [], {'max_length': '128', 'blank': 'True'})
},
'document_indexing.indextemplatenode': {
'Meta': {'object_name': 'IndexTemplateNode'},
'enabled': ('django.db.models.fields.BooleanField', [], {'default': 'True'}),
'expression': ('django.db.models.fields.CharField', [], {'max_length': '128'}),
'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}),
'index': ('django.db.models.fields.related.ForeignKey', [], {'to': "orm['document_indexing.Index']"}),
'level': ('django.db.models.fields.PositiveIntegerField', [], {'db_index': 'True'}),
'lft': ('django.db.models.fields.PositiveIntegerField', [], {'db_index': 'True'}),
'link_documents': ('django.db.models.fields.BooleanField', [], {'default': 'False'}),
'parent': ('mptt.fields.TreeForeignKey', [], {'blank': 'True', 'related_name': "'index_template_node'", 'null': 'True', 'to': "orm['document_indexing.IndexTemplateNode']"}),
'rght': ('django.db.models.fields.PositiveIntegerField', [], {'db_index': 'True'}),
'tree_id': ('django.db.models.fields.PositiveIntegerField', [], {'db_index': 'True'})
},
'documents.document': {
'Meta': {'ordering': "['-date_added']", 'object_name': 'Document'},
'date_added': ('django.db.models.fields.DateTimeField', [], {'db_index': 'True'}),
'description': ('django.db.models.fields.TextField', [], {'null': 'True', 'blank': 'True'}),
'document_type': ('django.db.models.fields.related.ForeignKey', [], {'to': "orm['documents.DocumentType']", 'null': 'True', 'blank': 'True'}),
'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}),
'uuid': ('django.db.models.fields.CharField', [], {'max_length': '48', 'blank': 'True'})
},
'documents.documenttype': {
'Meta': {'ordering': "['name']", 'object_name': 'DocumentType'},
'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}),
'name': ('django.db.models.fields.CharField', [], {'max_length': '32'})
},
'sites.site': {
'Meta': {'ordering': "('domain',)", 'object_name': 'Site', 'db_table': "'django_site'"},
'domain': ('django.db.models.fields.CharField', [], {'max_length': '100'}),
'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}),
'name': ('django.db.models.fields.CharField', [], {'max_length': '50'})
},
'taggit.tag': {
'Meta': {'object_name': 'Tag'},
'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}),
'name': ('django.db.models.fields.CharField', [], {'max_length': '100'}),
'slug': ('django.db.models.fields.SlugField', [], {'unique': 'True', 'max_length': '100', 'db_index': 'True'})
},
'taggit.taggeditem': {
'Meta': {'object_name': 'TaggedItem'},
'content_type': ('django.db.models.fields.related.ForeignKey', [], {'related_name': "'taggit_taggeditem_tagged_items'", 'to': "orm['contenttypes.ContentType']"}),
'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}),
'object_id': ('django.db.models.fields.IntegerField', [], {'db_index': 'True'}),
'tag': ('django.db.models.fields.related.ForeignKey', [], {'related_name': "'taggit_taggeditem_items'", 'to': "orm['taggit.Tag']"})
}
}
complete_apps = ['document_indexing']

View File

@@ -0,0 +1,153 @@
# encoding: utf-8
import datetime
from south.db import db
from south.v2 import SchemaMigration
from django.db import models
class Migration(SchemaMigration):
def forwards(self, orm):
# Adding unique constraint on 'Index', fields ['name']
db.create_unique('document_indexing_index', ['name'])
# Adding unique constraint on 'Index', fields ['title']
db.create_unique('document_indexing_index', ['title'])
def backwards(self, orm):
# Removing unique constraint on 'Index', fields ['title']
db.delete_unique('document_indexing_index', ['title'])
# Removing unique constraint on 'Index', fields ['name']
db.delete_unique('document_indexing_index', ['name'])
models = {
'auth.group': {
'Meta': {'object_name': 'Group'},
'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}),
'name': ('django.db.models.fields.CharField', [], {'unique': 'True', 'max_length': '80'}),
'permissions': ('django.db.models.fields.related.ManyToManyField', [], {'to': "orm['auth.Permission']", 'symmetrical': 'False', 'blank': 'True'})
},
'auth.permission': {
'Meta': {'ordering': "('content_type__app_label', 'content_type__model', 'codename')", 'unique_together': "(('content_type', 'codename'),)", 'object_name': 'Permission'},
'codename': ('django.db.models.fields.CharField', [], {'max_length': '100'}),
'content_type': ('django.db.models.fields.related.ForeignKey', [], {'to': "orm['contenttypes.ContentType']"}),
'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}),
'name': ('django.db.models.fields.CharField', [], {'max_length': '50'})
},
'auth.user': {
'Meta': {'object_name': 'User'},
'date_joined': ('django.db.models.fields.DateTimeField', [], {'default': 'datetime.datetime.now'}),
'email': ('django.db.models.fields.EmailField', [], {'max_length': '75', 'blank': 'True'}),
'first_name': ('django.db.models.fields.CharField', [], {'max_length': '30', 'blank': 'True'}),
'groups': ('django.db.models.fields.related.ManyToManyField', [], {'to': "orm['auth.Group']", 'symmetrical': 'False', 'blank': 'True'}),
'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}),
'is_active': ('django.db.models.fields.BooleanField', [], {'default': 'True'}),
'is_staff': ('django.db.models.fields.BooleanField', [], {'default': 'False'}),
'is_superuser': ('django.db.models.fields.BooleanField', [], {'default': 'False'}),
'last_login': ('django.db.models.fields.DateTimeField', [], {'default': 'datetime.datetime.now'}),
'last_name': ('django.db.models.fields.CharField', [], {'max_length': '30', 'blank': 'True'}),
'password': ('django.db.models.fields.CharField', [], {'max_length': '128'}),
'user_permissions': ('django.db.models.fields.related.ManyToManyField', [], {'to': "orm['auth.Permission']", 'symmetrical': 'False', 'blank': 'True'}),
'username': ('django.db.models.fields.CharField', [], {'unique': 'True', 'max_length': '30'})
},
'comments.comment': {
'Meta': {'ordering': "('submit_date',)", 'object_name': 'Comment', 'db_table': "'django_comments'"},
'comment': ('django.db.models.fields.TextField', [], {'max_length': '3000'}),
'content_type': ('django.db.models.fields.related.ForeignKey', [], {'related_name': "'content_type_set_for_comment'", 'to': "orm['contenttypes.ContentType']"}),
'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}),
'ip_address': ('django.db.models.fields.IPAddressField', [], {'max_length': '15', 'null': 'True', 'blank': 'True'}),
'is_public': ('django.db.models.fields.BooleanField', [], {'default': 'True'}),
'is_removed': ('django.db.models.fields.BooleanField', [], {'default': 'False'}),
'object_pk': ('django.db.models.fields.TextField', [], {}),
'site': ('django.db.models.fields.related.ForeignKey', [], {'to': "orm['sites.Site']"}),
'submit_date': ('django.db.models.fields.DateTimeField', [], {'default': 'None'}),
'user': ('django.db.models.fields.related.ForeignKey', [], {'blank': 'True', 'related_name': "'comment_comments'", 'null': 'True', 'to': "orm['auth.User']"}),
'user_email': ('django.db.models.fields.EmailField', [], {'max_length': '75', 'blank': 'True'}),
'user_name': ('django.db.models.fields.CharField', [], {'max_length': '50', 'blank': 'True'}),
'user_url': ('django.db.models.fields.URLField', [], {'max_length': '200', 'blank': 'True'})
},
'contenttypes.contenttype': {
'Meta': {'ordering': "('name',)", 'unique_together': "(('app_label', 'model'),)", 'object_name': 'ContentType', 'db_table': "'django_content_type'"},
'app_label': ('django.db.models.fields.CharField', [], {'max_length': '100'}),
'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}),
'model': ('django.db.models.fields.CharField', [], {'max_length': '100'}),
'name': ('django.db.models.fields.CharField', [], {'max_length': '100'})
},
'document_indexing.documentrenamecount': {
'Meta': {'object_name': 'DocumentRenameCount'},
'document': ('django.db.models.fields.related.ForeignKey', [], {'to': "orm['documents.Document']"}),
'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}),
'index_instance_node': ('django.db.models.fields.related.ForeignKey', [], {'to': "orm['document_indexing.IndexInstanceNode']"}),
'suffix': ('django.db.models.fields.PositiveIntegerField', [], {'blank': 'True'})
},
'document_indexing.index': {
'Meta': {'object_name': 'Index'},
'enabled': ('django.db.models.fields.BooleanField', [], {'default': 'True'}),
'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}),
'name': ('django.db.models.fields.CharField', [], {'unique': 'True', 'max_length': '64'}),
'title': ('django.db.models.fields.CharField', [], {'unique': 'True', 'max_length': '128'})
},
'document_indexing.indexinstancenode': {
'Meta': {'object_name': 'IndexInstanceNode'},
'documents': ('django.db.models.fields.related.ManyToManyField', [], {'to': "orm['documents.Document']", 'symmetrical': 'False'}),
'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}),
'index_template_node': ('django.db.models.fields.related.ForeignKey', [], {'to': "orm['document_indexing.IndexTemplateNode']"}),
'level': ('django.db.models.fields.PositiveIntegerField', [], {'db_index': 'True'}),
'lft': ('django.db.models.fields.PositiveIntegerField', [], {'db_index': 'True'}),
'parent': ('mptt.fields.TreeForeignKey', [], {'blank': 'True', 'related_name': "'index_instance_node'", 'null': 'True', 'to': "orm['document_indexing.IndexInstanceNode']"}),
'rght': ('django.db.models.fields.PositiveIntegerField', [], {'db_index': 'True'}),
'tree_id': ('django.db.models.fields.PositiveIntegerField', [], {'db_index': 'True'}),
'value': ('django.db.models.fields.CharField', [], {'max_length': '128', 'blank': 'True'})
},
'document_indexing.indextemplatenode': {
'Meta': {'object_name': 'IndexTemplateNode'},
'enabled': ('django.db.models.fields.BooleanField', [], {'default': 'True'}),
'expression': ('django.db.models.fields.CharField', [], {'max_length': '128'}),
'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}),
'index': ('django.db.models.fields.related.ForeignKey', [], {'to': "orm['document_indexing.Index']"}),
'level': ('django.db.models.fields.PositiveIntegerField', [], {'db_index': 'True'}),
'lft': ('django.db.models.fields.PositiveIntegerField', [], {'db_index': 'True'}),
'link_documents': ('django.db.models.fields.BooleanField', [], {'default': 'False'}),
'parent': ('mptt.fields.TreeForeignKey', [], {'blank': 'True', 'related_name': "'index_template_node'", 'null': 'True', 'to': "orm['document_indexing.IndexTemplateNode']"}),
'rght': ('django.db.models.fields.PositiveIntegerField', [], {'db_index': 'True'}),
'tree_id': ('django.db.models.fields.PositiveIntegerField', [], {'db_index': 'True'})
},
'documents.document': {
'Meta': {'ordering': "['-date_added']", 'object_name': 'Document'},
'date_added': ('django.db.models.fields.DateTimeField', [], {'db_index': 'True'}),
'description': ('django.db.models.fields.TextField', [], {'null': 'True', 'blank': 'True'}),
'document_type': ('django.db.models.fields.related.ForeignKey', [], {'to': "orm['documents.DocumentType']", 'null': 'True', 'blank': 'True'}),
'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}),
'uuid': ('django.db.models.fields.CharField', [], {'max_length': '48', 'blank': 'True'})
},
'documents.documenttype': {
'Meta': {'ordering': "['name']", 'object_name': 'DocumentType'},
'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}),
'name': ('django.db.models.fields.CharField', [], {'max_length': '32'})
},
'sites.site': {
'Meta': {'ordering': "('domain',)", 'object_name': 'Site', 'db_table': "'django_site'"},
'domain': ('django.db.models.fields.CharField', [], {'max_length': '100'}),
'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}),
'name': ('django.db.models.fields.CharField', [], {'max_length': '50'})
},
'taggit.tag': {
'Meta': {'object_name': 'Tag'},
'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}),
'name': ('django.db.models.fields.CharField', [], {'max_length': '100'}),
'slug': ('django.db.models.fields.SlugField', [], {'unique': 'True', 'max_length': '100', 'db_index': 'True'})
},
'taggit.taggeditem': {
'Meta': {'object_name': 'TaggedItem'},
'content_type': ('django.db.models.fields.related.ForeignKey', [], {'related_name': "'taggit_taggeditem_tagged_items'", 'to': "orm['contenttypes.ContentType']"}),
'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}),
'object_id': ('django.db.models.fields.IntegerField', [], {'db_index': 'True'}),
'tag': ('django.db.models.fields.related.ForeignKey', [], {'related_name': "'taggit_taggeditem_items'", 'to': "orm['taggit.Tag']"})
}
}
complete_apps = ['document_indexing']

View File

@@ -13,24 +13,54 @@ from .conf.settings import AVAILABLE_INDEXING_FUNCTIONS
available_indexing_functions_string = (_(u'Available functions: %s') % u','.join([u'%s()' % name for name, function in AVAILABLE_INDEXING_FUNCTIONS.items()])) if AVAILABLE_INDEXING_FUNCTIONS else u''
class Index(MPTTModel):
parent = TreeForeignKey('self', null=True, blank=True, related_name='index_meta_class')
expression = models.CharField(max_length=128, verbose_name=_(u'indexing expression'), help_text=_(u'Enter a python string expression to be evaluated.'))
# % available_indexing_functions_string)
enabled = models.BooleanField(default=True, verbose_name=_(u'enabled'))
link_documents = models.BooleanField(default=False, verbose_name=_(u'link documents'))
class Index(models.Model):
name = models.CharField(unique=True, max_length=64, verbose_name=_(u'name'), help_text=_(u'Internal name used to reference this index.'))
title = models.CharField(unique=True, max_length=128, verbose_name=_(u'title'), help_text=_(u'The name that will be visible to users.'))
enabled = models.BooleanField(default=True, verbose_name=_(u'enabled'), help_text=_(u'Causes this index to be visible and updated when document data changes.'))
@property
def template_root(self):
return self.indextemplatenode_set.get(parent=None)
@property
def instance_root(self):
return self.template_root.indexinstancenode_set.get()
def __unicode__(self):
return self.expression if not self.link_documents else u'%s/[document]' % self.expression
return self.title
@models.permalink
def get_absolute_url(self):
return ('index_instance_node_view', [self.instance_root.pk])
def save(self, *args, **kwargs):
super(Index, self).save(*args, **kwargs)
index_template_node_root, created = IndexTemplateNode.objects.get_or_create(parent=None, index=self)
class Meta:
verbose_name = _(u'index')
verbose_name_plural = _(u'indexes')
class IndexInstance(MPTTModel):
parent = TreeForeignKey('self', null=True, blank=True, related_name='index_meta_instance')
class IndexTemplateNode(MPTTModel):
parent = TreeForeignKey('self', null=True, blank=True, related_name='index_template_node')
index = models.ForeignKey(Index, verbose_name=_(u'index'))
expression = models.CharField(max_length=128, verbose_name=_(u'indexing expression'), help_text=_(u'Enter a python string expression to be evaluated.'))
# % available_indexing_functions_string)
enabled = models.BooleanField(default=True, verbose_name=_(u'enabled'), help_text=_(u'Causes this node to be visible and updated when document data changes.'))
link_documents = models.BooleanField(default=False, verbose_name=_(u'link documents'), help_text=_(u'Check this option to have this node act as a container for documents and not as a parent for further nodes.'))
def __unicode__(self):
return self.expression if not self.link_documents else u'%s/[document]' % self.expression
class Meta:
verbose_name = _(u'index template node')
verbose_name_plural = _(u'indexes template nodes')
class IndexInstanceNode(MPTTModel):
parent = TreeForeignKey('self', null=True, blank=True, related_name='index_instance_node')
index_template_node = models.ForeignKey(IndexTemplateNode, verbose_name=_(u'index template node'))
value = models.CharField(max_length=128, blank=True, verbose_name=_(u'value'))
documents = models.ManyToManyField(Document, verbose_name=_(u'documents'))
@@ -39,23 +69,20 @@ class IndexInstance(MPTTModel):
@models.permalink
def get_absolute_url(self):
return ('index_instance_list', [self.pk])
def get_document_list_display(self):
return u', '.join([d.file_filename for d in self.documents.all()])
return ('index_instance_node_view', [self.pk])
class Meta:
verbose_name = _(u'index instance')
verbose_name_plural = _(u'indexes instances')
verbose_name = _(u'index instance node')
verbose_name_plural = _(u'indexes instance nodes')
class DocumentRenameCount(models.Model):
index_instance = models.ForeignKey(IndexInstance, verbose_name=_(u'index instance'))
index_instance_node = models.ForeignKey(IndexInstanceNode, verbose_name=_(u'index instance'))
document = models.ForeignKey(Document, verbose_name=_(u'document'))
suffix = models.PositiveIntegerField(blank=True, verbose_name=(u'suffix'))
def __unicode__(self):
return u'%s - %s - %s' % (self.index_instance, self.document, self.suffix or u'0')
return u'%s - %s - %s' % (self.index_instance_node, self.document, self.suffix or u'0')
class Meta:
verbose_name = _(u'document rename count')

View File

@@ -1,22 +0,0 @@
from __future__ import absolute_import
import os
from .conf.settings import SUFFIX_SEPARATOR
def assemble_suffixed_filename(filename, suffix=0):
"""
Split document filename, to attach suffix to the name part then
re attacht the extension
"""
if suffix:
name, extension = filename.split(os.split(os.extsep))
return SUFFIX_SEPARATOR.join([name, unicode(suffix), os.extsep, extension])
else:
return filename
def assemble_path_from_list(directory_list):
return os.sep.join(directory_list)

View File

@@ -6,5 +6,10 @@ from permissions.models import PermissionNamespace, Permission
document_indexing_namespace = PermissionNamespace('document_indexing', _(u'Indexing'))
PERMISSION_DOCUMENT_INDEXING_SETUP = Permission.objects.register(document_indexing_namespace, 'document_index_setup', _(u'Configure document indexes'))
PERMISSION_DOCUMENT_INDEXING_CREATE = Permission.objects.register(document_indexing_namespace, 'document_index_create', _(u'Create new document indexes'))
PERMISSION_DOCUMENT_INDEXING_EDIT = Permission.objects.register(document_indexing_namespace, 'document_index_edit', _(u'Edit document indexes'))
PERMISSION_DOCUMENT_INDEXING_DELETE = Permission.objects.register(document_indexing_namespace, 'document_index_delete', _(u'Delete document indexes'))
PERMISSION_DOCUMENT_INDEXING_VIEW = Permission.objects.register(document_indexing_namespace, 'document_index_view', _(u'View document indexes'))
PERMISSION_DOCUMENT_INDEXING_REBUILD_INDEXES = Permission.objects.register(document_indexing_namespace, 'document_rebuild_indexes', _(u'Rebuild document indexes'))

Binary file not shown.

After

Width:  |  Height:  |  Size: 578 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 1.1 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 1.2 KiB

View File

@@ -0,0 +1,19 @@
from __future__ import absolute_import
from documents.models import Document
from .models import Index, IndexInstanceNode, DocumentRenameCount
from .filesystem import fs_delete_directory_recusive
from .api import update_indexes
def do_rebuild_all_indexes():
for index in Index.objects.all():
fs_delete_directory_recusive(index)
IndexInstanceNode.objects.all().delete()
DocumentRenameCount.objects.all().delete()
for document in Document.objects.all():
update_indexes(document)
return [] # Warnings - None

View File

@@ -1,9 +1,19 @@
from django.conf.urls.defaults import patterns, url
urlpatterns = patterns('document_indexing.views',
url(r'^(?P<index_id>\d+)/list/$', 'index_instance_list', (), 'index_instance_list'),
url(r'^list/$', 'index_instance_list', (), 'index_instance_list'),
url(r'^rebuild/all/$', 'rebuild_index_instances', (), 'rebuild_index_instances'),
url(r'^setup/index/list/$', 'index_setup_list', (), 'index_setup_list'),
url(r'^setup/index/create/$', 'index_setup_create', (), 'index_setup_create'),
url(r'^setup/index/(?P<index_pk>\d+)/edit/$', 'index_setup_edit', (), 'index_setup_edit'),
url(r'^setup/index/(?P<index_pk>\d+)/delete/$', 'index_setup_delete', (), 'index_setup_delete'),
url(r'^setup/index/(?P<index_pk>\d+)/view/$', 'index_setup_view', (), 'index_setup_view'),
url(r'^setup/template/node/(?P<parent_pk>\d+)/create/child/$', 'template_node_create', (), 'template_node_create'),
url(r'^setup/template/node/(?P<node_pk>\d+)/edit/$', 'template_node_edit', (), 'template_node_edit'),
url(r'^setup/template/node/(?P<node_pk>\d+)/delete/$', 'template_node_delete', (), 'template_node_delete'),
url(r'^index/list/$', 'index_list', (), 'index_list'),
url(r'^instance/node/(?P<index_instance_node_pk>\d+)/$', 'index_instance_node_view', (), 'index_instance_node_view'),
url(r'^rebuild/all/$', 'rebuild_index_instances', (), 'rebuild_index_instances'),
url(r'^list/for/document/(?P<document_id>\d+)/$', 'document_index_list', (), 'document_index_list'),
)

View File

@@ -1,3 +1,5 @@
# -*- coding: utf-8 -*-
from __future__ import absolute_import
from django.utils.translation import ugettext_lazy as _
@@ -5,46 +7,319 @@ from django.http import HttpResponseRedirect
from django.shortcuts import render_to_response, get_object_or_404
from django.template import RequestContext
from django.contrib import messages
from django.utils.safestring import mark_safe
from django.core.urlresolvers import reverse
from django.utils.html import conditional_escape, mark_safe
from django.core.exceptions import PermissionDenied
from permissions.models import Permission
from documents.permissions import PERMISSION_DOCUMENT_VIEW
from documents.models import Document
from documents.views import document_list
from common.utils import encapsulate
from acls.utils import apply_default_acls
from acls.models import AccessEntry
from .forms import IndexForm, IndexTemplateNodeForm
from .models import (Index, IndexTemplateNode, IndexInstanceNode)
from .tools import do_rebuild_all_indexes
from .widgets import (index_instance_item_link, get_breadcrumbs)
from .permissions import (PERMISSION_DOCUMENT_INDEXING_VIEW,
PERMISSION_DOCUMENT_INDEXING_REBUILD_INDEXES)
from .models import IndexInstance
from .api import (get_breadcrumbs, get_instance_link,
do_rebuild_all_indexes)
from .widgets import index_instance_item_link
PERMISSION_DOCUMENT_INDEXING_REBUILD_INDEXES,
PERMISSION_DOCUMENT_INDEXING_SETUP,
PERMISSION_DOCUMENT_INDEXING_CREATE,
PERMISSION_DOCUMENT_INDEXING_EDIT,
PERMISSION_DOCUMENT_INDEXING_DELETE
)
def index_instance_list(request, index_id=None):
Permission.objects.check_permissions(request.user, [PERMISSION_DOCUMENT_INDEXING_VIEW])
# Setup views
def index_setup_list(request):
context = {
'title': _(u'indexes'),
'hide_object': True,
'list_object_variable_name': 'index',
'extra_columns': [
{'name': _(u'name'), 'attribute': 'name'},
{'name': _(u'title'), 'attribute': 'title'},
]
}
if index_id:
index_instance = get_object_or_404(IndexInstance, pk=index_id)
index_instance_list = [index for index in index_instance.get_children().order_by('value')]
breadcrumbs = get_breadcrumbs(index_instance)
if index_instance.documents.count():
for document in index_instance.documents.all().order_by('file_filename'):
index_instance_list.append(document)
queryset = Index.objects.all()
try:
Permission.objects.check_permissions(request.user, [PERMISSION_DOCUMENT_INDEXING_SETUP])
except PermissionDenied:
queryset = AccessEntry.objects.filter_objects_by_access(PERMISSION_DOCUMENT_INDEXING_SETUP, request.user, queryset)
context['object_list'] = queryset
return render_to_response('generic_list.html',
context,
context_instance=RequestContext(request)
)
def index_setup_create(request):
Permission.objects.check_permissions(request.user, [PERMISSION_DOCUMENT_INDEXING_CREATE])
if request.method == 'POST':
form = IndexForm(request.POST)
if form.is_valid():
index = form.save()
apply_default_acls(index, request.user)
messages.success(request, _(u'Index created successfully.'))
return HttpResponseRedirect(reverse('index_setup_list'))
else:
index_instance_list = IndexInstance.objects.filter(parent=None)
breadcrumbs = get_instance_link()
index_instance = None
form = IndexForm()
return render_to_response('generic_form.html', {
'title': _(u'create index'),
'form': form,
},
context_instance=RequestContext(request))
def index_setup_edit(request, index_pk):
index = get_object_or_404(Index, pk=index_pk)
try:
Permission.objects.check_permissions(request.user, [PERMISSION_DOCUMENT_INDEXING_EDIT])
except PermissionDenied:
AccessEntry.objects.check_access(PERMISSION_DOCUMENT_INDEXING_CREATE, request.user, index)
if request.method == 'POST':
form = IndexForm(request.POST, instance=index)
if form.is_valid():
form.save()
messages.success(request, _(u'Index edited successfully'))
return HttpResponseRedirect(reverse('index_setup_list'))
else:
form = IndexForm(instance=index)
return render_to_response('generic_form.html', {
'title': _(u'edit index: %s') % index,
'form': form,
'index': index,
'object_name': _(u'index'),
'navigation_object_name': 'index',
},
context_instance=RequestContext(request))
def index_setup_delete(request, index_pk):
index = get_object_or_404(Index, pk=index_pk)
try:
Permission.objects.check_permissions(request.user, [PERMISSION_DOCUMENT_INDEXING_DELETE])
except PermissionDenied:
AccessEntry.objects.check_access(PERMISSION_DOCUMENT_INDEXING_DELETE, request.user, index)
post_action_redirect = reverse('index_setup_list')
previous = request.POST.get('previous', request.GET.get('previous', request.META.get('HTTP_REFERER', '/')))
next = request.POST.get('next', request.GET.get('next', post_action_redirect if post_action_redirect else request.META.get('HTTP_REFERER', '/')))
if request.method == 'POST':
try:
index.delete()
messages.success(request, _(u'Index: %s deleted successfully.') % index)
except Exception, e:
messages.error(request, _(u'Index: %(index)s delete error: %(error)s') % {
'index': index, 'error': e})
return HttpResponseRedirect(next)
context = {
'index': index,
'object_name': _(u'index'),
'navigation_object_name': 'index',
'delete_view': True,
'previous': previous,
'next': next,
'title': _(u'Are you sure you with to delete the index: %s?') % index,
'form_icon': u'tab_delete.png',
}
return render_to_response('generic_confirm.html', context,
context_instance=RequestContext(request))
def index_setup_view(request, index_pk):
index = get_object_or_404(Index, pk=index_pk)
try:
Permission.objects.check_permissions(request.user, [PERMISSION_DOCUMENT_INDEXING_SETUP])
except PermissionDenied:
AccessEntry.objects.check_access(PERMISSION_DOCUMENT_INDEXING_SETUP, request.user, index)
root, created = IndexTemplateNode.objects.get_or_create(parent=None, index=index)
object_list = root.get_descendants(include_self=True)
context = {
'object_list': object_list,
'index': index,
'object_name': _(u'index'),
'list_object_variable_name': 'node',
'navigation_object_name': 'index',
'title': _(u'tree template nodes for index: %s') % index,
'hide_object': True,
'extra_columns': [
{'name': _(u'level'), 'attribute': encapsulate(lambda x: u''.join([mark_safe(conditional_escape(u'--') * (getattr(x, x._mptt_meta.level_attr) - 0)), unicode(x if x.parent else 'root') ] ))},
],
}
return render_to_response('generic_list.html', context,
context_instance=RequestContext(request))
# Node views
def template_node_create(request, parent_pk):
parent_node = get_object_or_404(IndexTemplateNode, pk=parent_pk)
try:
Permission.objects.check_permissions(request.user, [PERMISSION_DOCUMENT_INDEXING_SETUP])
except PermissionDenied:
AccessEntry.objects.check_access(PERMISSION_DOCUMENT_INDEXING_SETUP, request.user, parent_node.index)
if request.method == 'POST':
form = IndexTemplateNodeForm(request.POST)
if form.is_valid():
node = form.save()
messages.success(request, _(u'Index template node created successfully.'))
return HttpResponseRedirect(reverse('index_setup_view', args=[node.index.pk]))
else:
form = IndexTemplateNodeForm(initial={'index': parent_node.index, 'parent': parent_node})
return render_to_response('generic_form.html', {
'title': _(u'create child node'),
'form': form,
'index': parent_node.index,
'object_name': _(u'index'),
'navigation_object_name': 'index',
},
context_instance=RequestContext(request))
def template_node_edit(request, node_pk):
node = get_object_or_404(IndexTemplateNode, pk=node_pk)
try:
Permission.objects.check_permissions(request.user, [PERMISSION_DOCUMENT_INDEXING_SETUP])
except PermissionDenied:
AccessEntry.objects.check_access(PERMISSION_DOCUMENT_INDEXING_SETUP, request.user, node.index)
if request.method == 'POST':
form = IndexTemplateNodeForm(request.POST, instance=node)
if form.is_valid():
form.save()
messages.success(request, _(u'Index template node edited successfully'))
return HttpResponseRedirect(reverse('index_setup_view', args=[node.index.pk]))
else:
form = IndexTemplateNodeForm(instance=node)
return render_to_response('generic_form.html', {
'title': _(u'edit index template node: %s') % node,
'form': form,
'index': node.index,
'node': node,
'navigation_object_list': [
{'object': 'index', 'name': _(u'index')},
{'object': 'node', 'name': _(u'node')}
],
},
context_instance=RequestContext(request))
def template_node_delete(request, node_pk):
node = get_object_or_404(IndexTemplateNode, pk=node_pk)
try:
Permission.objects.check_permissions(request.user, [PERMISSION_DOCUMENT_INDEXING_SETUP])
except PermissionDenied:
AccessEntry.objects.check_access(PERMISSION_DOCUMENT_INDEXING_SETUP, request.user, node.index)
post_action_redirect = reverse('index_setup_view', args=[node.index.pk])
previous = request.POST.get('previous', request.GET.get('previous', request.META.get('HTTP_REFERER', '/')))
next = request.POST.get('next', request.GET.get('next', post_action_redirect if post_action_redirect else request.META.get('HTTP_REFERER', '/')))
if request.method == 'POST':
try:
node.delete()
messages.success(request, _(u'Node: %s deleted successfully.') % node)
except Exception, e:
messages.error(request, _(u'Node: %(node)s delete error: %(error)s') % {
'node': node, 'error': e})
return HttpResponseRedirect(next)
context = {
'delete_view': True,
'previous': previous,
'next': next,
'title': _(u'Are you sure you with to delete the index template node: %s?') % node,
'form_icon': u'textfield_delete.png',
'index': node.index,
'node': node,
'navigation_object_list': [
{'object': 'index', 'name': _(u'index')},
{'object': 'node', 'name': _(u'node')}
],
}
return render_to_response('generic_confirm.html', context,
context_instance=RequestContext(request))
def index_list(request):
context = {
'title': _(u'indexes'),
#'hide_object': True,
#'list_object_variable_name': 'index',
#'extra_columns': [
# {'name': _(u'elements'), 'attribute': 'root'},
# {'name': _(u'name'), 'attribute': 'name'},
# {'name': _(u'title'), 'attribute': 'title'},
#],
'overrided_object_links': [{}],
}
queryset = Index.objects.filter(enabled=True)
try:
Permission.objects.check_permissions(request.user, [PERMISSION_DOCUMENT_INDEXING_VIEW])
except PermissionDenied:
queryset = AccessEntry.objects.filter_objects_by_access(PERMISSION_DOCUMENT_INDEXING_VIEW, request.user, queryset)
context['object_list'] = queryset
return render_to_response('generic_list.html',
context,
context_instance=RequestContext(request)
)
def index_instance_node_view(request, index_instance_node_pk):
index_instance = get_object_or_404(IndexInstanceNode, pk=index_instance_node_pk)
index_instance_list = [index for index in index_instance.get_children().order_by('value')]
breadcrumbs = get_breadcrumbs(index_instance)
try:
Permission.objects.check_permissions(request.user, [PERMISSION_DOCUMENT_INDEXING_VIEW])
except PermissionDenied:
AccessEntry.objects.check_access(PERMISSION_DOCUMENT_INDEXING_VIEW, request.user, index_instance.index)
title = mark_safe(_(u'contents for index: %s') % breadcrumbs)
if index_instance:
if index_instance.index.link_documents:
if index_instance.index_template_node.link_documents:
# Document list, use the document_list view for consistency
return document_list(
request,
title=title,
object_list=index_instance_list,
object_list=index_instance.documents.all(),
extra_context={
'object': index_instance
}
@@ -54,12 +329,12 @@ def index_instance_list(request, index_id=None):
'object_list': index_instance_list,
'extra_columns_preffixed': [
{
'name': _(u'index'),
'name': _(u'node'),
'attribute': encapsulate(lambda x: index_instance_item_link(x))
},
{
'name': _(u'items'),
'attribute': encapsulate(lambda x: x.documents.count() if x.index.link_documents else x.get_children().count())
'attribute': encapsulate(lambda x: x.documents.count() if x.index_template_node.link_documents else x.get_children().count())
}
],
'title': title,
@@ -98,12 +373,16 @@ def rebuild_index_instances(request):
def document_index_list(request, document_id):
Permission.objects.check_permissions(request.user, [PERMISSION_DOCUMENT_VIEW, PERMISSION_DOCUMENT_INDEXING_VIEW])
document = get_object_or_404(Document, pk=document_id)
object_list = []
for index_instance in document.indexinstance_set.all():
queryset = document.indexinstancenode_set.all()
try:
Permission.objects.check_permissions(request.user, [PERMISSION_DOCUMENT_VIEW, PERMISSION_DOCUMENT_INDEXING_VIEW])
except PermissionDenied:
queryset = AccessEntry.objects.filter_objects_by_access(PERMISSION_DOCUMENT_INDEXING_VIEW, request.user, queryset)
for index_instance in queryset:
object_list.append(get_breadcrumbs(index_instance, single_link=True, include_count=True))
return render_to_response('generic_list.html', {

View File

@@ -1,14 +1,16 @@
from __future__ import absolute_import
from django.utils.safestring import mark_safe
from document_indexing.models import IndexInstance
from .models import IndexInstanceNode
FOLDER_W_DOCUMENTS = u'folder_page'
FOLDER_ICON = u'folder'
def index_instance_item_link(index_instance_item):
if isinstance(index_instance_item, IndexInstance):
if index_instance_item.index.link_documents:
if isinstance(index_instance_item, IndexInstanceNode):
if index_instance_item.index_template_node.link_documents:
icon = FOLDER_W_DOCUMENTS
else:
icon = FOLDER_ICON
@@ -20,3 +22,52 @@ def index_instance_item_link(index_instance_item):
'icon_template': icon_template,
'text': index_instance_item
})
def get_instance_link(index_instance_node, text=None, simple=False):
"""
Return an HTML anchor to an index instance
"""
if simple:
# Just display the instance's value or overrided text, no
# HTML anchor
template = u'%(value)s'
else:
template = u'<a href="%(url)s">%(value)s</a>'
return template % {
'url': index_instance_node.get_absolute_url(),
'value': text if text else (index_instance_node if index_instance_node.parent else index_instance_node.index_template_node.index)
}
def get_breadcrumbs(index_instance, simple=False, single_link=False, include_count=False):
"""
Return a joined string of HTML anchors to every index instance's
parent from the root of the tree to the index instance
"""
result = []
if single_link:
# Return the entire breadcrumb path as a single HTML anchor
simple = True
#result.append(get_instance_link(index_instance.get_root(), simple=simple))
for instance in index_instance.get_ancestors():
result.append(get_instance_link(instance, simple=simple))
result.append(get_instance_link(index_instance, simple=simple))
output = []
if include_count:
output.append(u'(%d)' % index_instance.documents.count())
if single_link:
# Return the entire breadcrumb path as a single HTML anchor
output.insert(0, get_instance_link(index_instance_node=index_instance, text=(u' / '.join(result))))
return mark_safe(u' '.join(output))
else:
output.insert(0, u' / '.join(result))
return mark_safe(u' '.join(output))

View File

@@ -3,7 +3,7 @@ from __future__ import absolute_import
from django.db import models
from django.db.models import Q
from metadata.classes import MetadataObject
from metadata.classes import MetadataClass
from documents.models import Document
from .literals import INCLUSION_AND, INCLUSION_OR
@@ -18,7 +18,7 @@ class SmartLinkManager(models.Manager):
metadata_dict[document_metadata.metadata_type.name] = document_metadata.value
eval_dict = {}
eval_dict['document'] = document
eval_dict['metadata'] = MetadataObject(metadata_dict)
eval_dict['metadata'] = MetadataClass(metadata_dict)
if smart_link_obj:
smart_link_qs = self.model.objects.filter(Q(enabled=True) & Q(pk=smart_link_obj.pk))

View File

@@ -1,7 +1,7 @@
from django.utils.translation import ugettext_lazy as _
class MetadataObject(object):
class MetadataClass(object):
def __init__(self, dictionary):
self.dictionary = dictionary

View File

@@ -122,6 +122,19 @@ column after those is ignored.
* The ``--skip-repeated`` tells the importedr to not stop when finding
that a user already exists in the database.
Refactored document indexing
~~~~~~~~~~~~~~~~~~~~~~~~~~~~
The document indexing functionality has been improved and moved from experimental
stage to beta stage. Index configuration menus are now available on the
``Setup`` menu and allows administrators to create a skeleton tree that will
be populated with document links depending on their metadata and properties.
This populated tree can also be mirrored on the physical filesystem and shared
using Samba or another filesharing server giving users a structured view
of the documents contained within **Mayan EDMS** from the ``Indexes`` tab
or from a mirrored index shared via the network. A new configuration option
has been added, :setting:`DOCUMENT_INDEXING_FILESYSTEM_SERVING`, which maps
the index internal name with the physical directory where such index will be
mirrored on disk.
Upgrading from a previous version
=================================
@@ -191,15 +204,21 @@ so write down your role permission setup before upgrading.
Bugs fixed
==========
* Issue #17, special thanks to Dave Herring for all the help including
access to a machine suffering with the issue.
access to a machine suffering with the issue, and to Сергей Глита for
his research and eventual find of the core cause.
* Statistics fixes.
* Fixed get_image_cache_name regression in the OCR app.
Stuff removed
=============
* Removal of the OCR_CACHE_URI configuration option.
* Support for Celery and Sentry has been drop
for now.
* Removed the 'db_index' argument from Text fields definition and
migrations as it was causing error messages for MySQL users, thanks to
Сергей Глита for reporting this one.
* Configuration options removed:
* OCR_CACHE_URI
* DOCUMENT_INDEXING_FILESYSTEM_FILESERVING_PATH - Use the newest :setting:`DOCUMENT_INDEXING_FILESYSTEM_SERVING`
* DOCUMENT_INDEXING_FILESYSTEM_FILESERVING_ENABLE - Use the newest :setting:`DOCUMENT_INDEXING_FILESYSTEM_SERVING`

View File

@@ -297,21 +297,15 @@ DOCUMENT_INDEXING_FILESYSTEM_MAX_SUFFIX_COUNT
Default: ``1000``
.. setting:: DOCUMENT_INDEXING_FILESYSTEM_FILESERVING_PATH
.. setting:: DOCUMENT_INDEXING_FILESYSTEM_SERVING
DOCUMENT_INDEXING_FILESYSTEM_FILESERVING_PATH
---------------------------------------------
Default: ``/tmp/mayan/documents``
.. setting:: DOCUMENT_INDEXING_FILESYSTEM_FILESERVING_ENABLE
DOCUMENT_INDEXING_FILESYSTEM_SERVING
------------------------------------
Default: ``{}``
A dictionary that maps the index name and where on the filesystem that index will be mirrored.
DOCUMENT_INDEXING_FILESYSTEM_FILESERVING_ENABLE
-----------------------------------------------
Default: ``True``
OCR
===