Added a new document source: 'watched folder'

This commit is contained in:
Roberto Rosario
2011-07-27 02:43:22 -04:00
parent 529a9e7eca
commit 9d965face3
8 changed files with 98 additions and 18 deletions

View File

@@ -21,4 +21,5 @@ def register_interval_job(name, title, func, weeks=0, days=0, hours=0, minutes=0
def remove_job(name): def remove_job(name):
if name in registered_jobs: if name in registered_jobs:
scheduler.unschedule_job(registered_jobs[name]['job']) scheduler.unschedule_job(registered_jobs[name]['job'])
registered_jobs.pop(name)

View File

@@ -6,7 +6,8 @@ from navigation.api import register_links, \
from permissions.api import register_permission, set_namespace_title from permissions.api import register_permission, set_namespace_title
from sources.staging import StagingFile from sources.staging import StagingFile
from sources.models import WebForm, StagingFolder, SourceTransformation from sources.models import WebForm, StagingFolder, SourceTransformation, \
WatchFolder
from sources.widgets import staging_file_thumbnail from sources.widgets import staging_file_thumbnail
PERMISSION_SOURCES_SETUP_VIEW = {'namespace': 'sources_setup', 'name': 'sources_setup_view', 'label': _(u'View existing document sources')} PERMISSION_SOURCES_SETUP_VIEW = {'namespace': 'sources_setup', 'name': 'sources_setup_view', 'label': _(u'View existing document sources')}
@@ -24,7 +25,8 @@ staging_file_preview = {'text': _(u'preview'), 'class': 'fancybox-noscaling', 'v
staging_file_delete = {'text': _(u'delete'), 'view': 'staging_file_delete', 'args': ['source.source_type', 'source.pk', 'object.id'], 'famfam': 'delete', 'keep_query': True} staging_file_delete = {'text': _(u'delete'), 'view': 'staging_file_delete', 'args': ['source.source_type', 'source.pk', 'object.id'], 'famfam': 'delete', 'keep_query': True}
setup_web_form_list = {'text': _(u'web forms'), 'view': 'setup_web_form_list', 'famfam': 'application_form', 'children_classes': [WebForm]} setup_web_form_list = {'text': _(u'web forms'), 'view': 'setup_web_form_list', 'famfam': 'application_form', 'children_classes': [WebForm]}
setup_staging_folder_list = {'text': _(u'staging folders'), 'view': 'setup_staging_folder_list', 'famfam': 'folder_magnify', 'children_classes': [StagingFolder]} setup_staging_folder_list = {'text': _(u'staging folders'), 'view': 'setup_staging_folder_list', 'famfam': 'folder_camera', 'children_classes': [StagingFolder]}
setup_watch_folder_list = {'text': _(u'watch folders'), 'view': 'setup_watch_folder_list', 'famfam': 'folder_magnify', 'children_classes': [WatchFolder]}
setup_source_edit = {'text': _(u'edit'), 'view': 'setup_source_edit', 'args': ['source.source_type', 'source.pk'], 'famfam': 'application_form_edit'} setup_source_edit = {'text': _(u'edit'), 'view': 'setup_source_edit', 'args': ['source.source_type', 'source.pk'], 'famfam': 'application_form_edit'}
setup_source_delete = {'text': _(u'delete'), 'view': 'setup_source_delete', 'args': ['source.source_type', 'source.pk'], 'famfam': 'application_form_delete'} setup_source_delete = {'text': _(u'delete'), 'view': 'setup_source_delete', 'args': ['source.source_type', 'source.pk'], 'famfam': 'application_form_delete'}
@@ -41,19 +43,22 @@ register_links(StagingFile, [staging_file_delete])
register_links(SourceTransformation, [setup_source_transformation_edit, setup_source_transformation_delete]) register_links(SourceTransformation, [setup_source_transformation_edit, setup_source_transformation_delete])
register_links(['setup_web_form_list', 'setup_staging_folder_list', 'setup_source_create'], [setup_web_form_list, setup_staging_folder_list], menu_name='form_header') register_links(['setup_web_form_list', 'setup_staging_folder_list', 'setup_watch_folder_list', 'setup_source_create'], [setup_web_form_list, setup_staging_folder_list, setup_watch_folder_list], menu_name='form_header')
register_links(WebForm, [setup_web_form_list, setup_staging_folder_list], menu_name='form_header') register_links(WebForm, [setup_web_form_list, setup_staging_folder_list, setup_watch_folder_list], menu_name='form_header')
register_links(WebForm, [setup_source_transformation_list, setup_source_edit, setup_source_delete]) register_links(WebForm, [setup_source_transformation_list, setup_source_edit, setup_source_delete])
register_links(['setup_web_form_list', 'setup_staging_folder_list', 'setup_source_edit', 'setup_source_delete', 'setup_source_create'], [setup_source_create], menu_name='sidebar') register_links(['setup_web_form_list', 'setup_staging_folder_list', 'setup_watch_folder_list', 'setup_source_edit', 'setup_source_delete', 'setup_source_create'], [setup_source_create], menu_name='sidebar')
register_links(StagingFolder, [setup_web_form_list, setup_staging_folder_list], menu_name='form_header') register_links(StagingFolder, [setup_web_form_list, setup_staging_folder_list, setup_watch_folder_list], menu_name='form_header')
register_links(StagingFolder, [setup_source_transformation_list, setup_source_edit, setup_source_delete]) register_links(StagingFolder, [setup_source_transformation_list, setup_source_edit, setup_source_delete])
register_links(WatchFolder, [setup_web_form_list, setup_staging_folder_list, setup_watch_folder_list], menu_name='form_header')
register_links(WatchFolder, [setup_source_transformation_list, setup_source_edit, setup_source_delete])
register_links(['setup_source_transformation_create', 'setup_source_transformation_edit', 'setup_source_transformation_delete', 'setup_source_transformation_list'], [setup_source_transformation_create], menu_name='sidebar') register_links(['setup_source_transformation_create', 'setup_source_transformation_edit', 'setup_source_transformation_delete', 'setup_source_transformation_list'], [setup_source_transformation_create], menu_name='sidebar')
source_views = ['setup_web_form_list', 'setup_staging_folder_list', 'setup_source_edit', 'setup_source_delete', 'setup_source_create', 'setup_source_transformation_list', 'setup_source_transformation_edit', 'setup_source_transformation_delete', 'setup_source_transformation_create'] source_views = ['setup_web_form_list', 'setup_staging_folder_list', 'setup_watch_folder_list', 'setup_source_edit', 'setup_source_delete', 'setup_source_create', 'setup_source_transformation_list', 'setup_source_transformation_edit', 'setup_source_transformation_delete', 'setup_source_transformation_create']
register_model_list_columns(StagingFile, [ register_model_list_columns(StagingFile, [
{'name':_(u'thumbnail'), 'attribute': {'name':_(u'thumbnail'), 'attribute':

View File

@@ -4,7 +4,8 @@ from django.utils.translation import ugettext
from documents.forms import DocumentForm from documents.forms import DocumentForm
from sources.models import WebForm, StagingFolder, SourceTransformation from sources.models import WebForm, StagingFolder, SourceTransformation, \
WatchFolder
from sources.widgets import FamFamRadioSelect from sources.widgets import FamFamRadioSelect
from sources.utils import validate_whitelist_blacklist from sources.utils import validate_whitelist_blacklist
@@ -87,6 +88,11 @@ class StagingFolderSetupForm(forms.ModelForm):
model = StagingFolder model = StagingFolder
class WatchFolderSetupForm(forms.ModelForm):
class Meta:
model = WatchFolder
class SourceTransformationForm(forms.ModelForm): class SourceTransformationForm(forms.ModelForm):
class Meta: class Meta:
model = SourceTransformation model = SourceTransformation

View File

@@ -41,13 +41,16 @@ SOURCE_ICON_CHOICES = (
SOURCE_CHOICE_WEB_FORM = 'webform' SOURCE_CHOICE_WEB_FORM = 'webform'
SOURCE_CHOICE_STAGING = 'staging' SOURCE_CHOICE_STAGING = 'staging'
SOURCE_CHOICE_WATCH = 'watch'
SOURCE_CHOICES = ( SOURCE_CHOICES = (
(SOURCE_CHOICE_WEB_FORM, _(u'web form')), (SOURCE_CHOICE_WEB_FORM, _(u'web form')),
(SOURCE_CHOICE_STAGING, _(u'server staging folder')), (SOURCE_CHOICE_STAGING, _(u'server staging folder')),
(SOURCE_CHOICE_WATCH, _(u'server watch folder')),
) )
SOURCE_CHOICES_PLURAL = ( SOURCE_CHOICES_PLURAL = (
(SOURCE_CHOICE_WEB_FORM, _(u'web forms')), (SOURCE_CHOICE_WEB_FORM, _(u'web forms')),
(SOURCE_CHOICE_STAGING, _(u'server staging folders')), (SOURCE_CHOICE_STAGING, _(u'server staging folders')),
(SOURCE_CHOICE_WATCH, _(u'server watch folders')),
) )

View File

@@ -10,12 +10,13 @@ from documents.models import DocumentType
from metadata.models import MetadataType from metadata.models import MetadataType
from converter.api import get_available_transformations_choices from converter.api import get_available_transformations_choices
from converter.literals import DIMENSION_SEPARATOR from converter.literals import DIMENSION_SEPARATOR
from scheduler.api import register_interval_job, remove_job
from sources.managers import SourceTransformationManager from sources.managers import SourceTransformationManager
from sources.literals import SOURCE_CHOICES, SOURCE_CHOICES_PLURAL, \ from sources.literals import SOURCE_CHOICES, SOURCE_CHOICES_PLURAL, \
SOURCE_INTERACTIVE_UNCOMPRESS_CHOICES, SOURCE_CHOICE_WEB_FORM, \ SOURCE_INTERACTIVE_UNCOMPRESS_CHOICES, SOURCE_CHOICE_WEB_FORM, \
SOURCE_CHOICE_STAGING, SOURCE_ICON_DISK, SOURCE_ICON_DRIVE, \ SOURCE_CHOICE_STAGING, SOURCE_ICON_DISK, SOURCE_ICON_DRIVE, \
SOURCE_ICON_CHOICES SOURCE_ICON_CHOICES, SOURCE_CHOICE_WATCH, SOURCE_UNCOMPRESS_CHOICES
class BaseModel(models.Model): class BaseModel(models.Model):
@@ -77,7 +78,7 @@ class StagingFolder(InteractiveBaseModel):
class Meta(InteractiveBaseModel.Meta): class Meta(InteractiveBaseModel.Meta):
verbose_name = _(u'staging folder') verbose_name = _(u'staging folder')
verbose_name_plural = _(u'staging folder') verbose_name_plural = _(u'staging folders')
''' '''
class SourceMetadata(models.Model): class SourceMetadata(models.Model):
@@ -107,6 +108,29 @@ class WebForm(InteractiveBaseModel):
verbose_name = _(u'web form') verbose_name = _(u'web form')
verbose_name_plural = _(u'web forms') verbose_name_plural = _(u'web forms')
def test():
print 'WatchFolder'
class WatchFolder(BaseModel):
is_interactive = False
source_type = SOURCE_CHOICE_WATCH
folder_path = models.CharField(max_length=255, verbose_name=_(u'folder path'), help_text=_(u'Server side filesystem path.'))
uncompress = models.CharField(max_length=1, choices=SOURCE_UNCOMPRESS_CHOICES, verbose_name=_(u'uncompress'), help_text=_(u'Whether to expand or not compressed archives.'))
delete_after_upload = models.BooleanField(default=True, verbose_name=_(u'delete after upload'), help_text=_(u'Delete the file after is has been successfully uploaded.'))
interval = models.PositiveIntegerField(verbose_name=_(u'interval'), help_text=_(u'Inverval in seconds where the watch folder path is checked for new documents.'))
def save(self, *args, **kwargs):
if self.pk:
remove_job('watch_folder_%d' % self.pk)
super(WatchFolder, self).save(*args, **kwargs)
if self.enabled:
register_interval_job('watch_folder_%d' % self.pk, self.fullname(), test, seconds=self.interval)
class Meta(BaseModel.Meta):
verbose_name = _(u'watch folder')
verbose_name_plural = _(u'watch folders')
class ArgumentsValidator(object): class ArgumentsValidator(object):
message = _(u'Enter a valid value.') message = _(u'Enter a valid value.')

View File

@@ -1,6 +1,7 @@
from django.conf.urls.defaults import patterns, url from django.conf.urls.defaults import patterns, url
from sources.literals import SOURCE_CHOICE_WEB_FORM, SOURCE_CHOICE_STAGING from sources.literals import SOURCE_CHOICE_WEB_FORM, SOURCE_CHOICE_STAGING, \
SOURCE_CHOICE_WATCH
urlpatterns = patterns('sources.views', urlpatterns = patterns('sources.views',
url(r'^staging_file/type/(?P<source_type>\w+)/(?P<source_id>\d+)/(?P<staging_file_id>\w+)/preview/$', 'staging_file_preview', (), 'staging_file_preview'), url(r'^staging_file/type/(?P<source_type>\w+)/(?P<source_id>\d+)/(?P<staging_file_id>\w+)/preview/$', 'staging_file_preview', (), 'staging_file_preview'),
@@ -13,8 +14,8 @@ urlpatterns = patterns('sources.views',
#Setup views #Setup views
url(r'^setup/interactive/%s/list/$' % SOURCE_CHOICE_WEB_FORM, 'setup_source_list', {'source_type': SOURCE_CHOICE_WEB_FORM}, 'setup_web_form_list'), url(r'^setup/interactive/%s/list/$' % SOURCE_CHOICE_WEB_FORM, 'setup_source_list', {'source_type': SOURCE_CHOICE_WEB_FORM}, 'setup_web_form_list'),
url(r'^setup/interactive/%s/list/$' % SOURCE_CHOICE_STAGING, 'setup_source_list', {'source_type': SOURCE_CHOICE_STAGING}, 'setup_staging_folder_list'), url(r'^setup/interactive/%s/list/$' % SOURCE_CHOICE_STAGING, 'setup_source_list', {'source_type': SOURCE_CHOICE_STAGING}, 'setup_staging_folder_list'),
url(r'^setup/interactive/%s/list/$' % SOURCE_CHOICE_WATCH, 'setup_source_list', {'source_type': SOURCE_CHOICE_WATCH}, 'setup_watch_folder_list'),
url(r'^setup/interactive/(?P<source_type>\w+)/list/$', 'setup_source_list', (), 'setup_source_list'), url(r'^setup/interactive/(?P<source_type>\w+)/list/$', 'setup_source_list', (), 'setup_source_list'),
url(r'^setup/interactive/(?P<source_type>\w+)/(?P<source_id>\d+)/edit/$', 'setup_source_edit', (), 'setup_source_edit'), url(r'^setup/interactive/(?P<source_type>\w+)/(?P<source_id>\d+)/edit/$', 'setup_source_edit', (), 'setup_source_edit'),

View File

@@ -26,12 +26,15 @@ from metadata.api import save_metadata_list, \
from permissions.api import check_permissions from permissions.api import check_permissions
import sendfile import sendfile
from sources.models import WebForm, StagingFolder, SourceTransformation from sources.models import WebForm, StagingFolder, SourceTransformation, \
from sources.literals import SOURCE_CHOICE_WEB_FORM, SOURCE_CHOICE_STAGING WatchFolder
from sources.literals import SOURCE_CHOICE_WEB_FORM, SOURCE_CHOICE_STAGING, \
SOURCE_CHOICE_WATCH
from sources.literals import SOURCE_UNCOMPRESS_CHOICE_Y, \ from sources.literals import SOURCE_UNCOMPRESS_CHOICE_Y, \
SOURCE_UNCOMPRESS_CHOICE_ASK SOURCE_UNCOMPRESS_CHOICE_ASK
from sources.staging import create_staging_file_class, StagingFile from sources.staging import create_staging_file_class, StagingFile
from sources.forms import StagingDocumentForm, WebFormForm from sources.forms import StagingDocumentForm, WebFormForm, \
WatchFolderSetupForm
from sources.forms import WebFormSetupForm, StagingFolderSetupForm from sources.forms import WebFormSetupForm, StagingFolderSetupForm
from sources.forms import SourceTransformationForm, SourceTransformationForm_create from sources.forms import SourceTransformationForm, SourceTransformationForm_create
from sources import PERMISSION_SOURCES_SETUP_VIEW, \ from sources import PERMISSION_SOURCES_SETUP_VIEW, \
@@ -369,6 +372,8 @@ def setup_source_list(request, source_type):
cls = WebForm cls = WebForm
elif source_type == SOURCE_CHOICE_STAGING: elif source_type == SOURCE_CHOICE_STAGING:
cls = StagingFolder cls = StagingFolder
elif source_type == SOURCE_CHOICE_WATCH:
cls = WatchFolder
context = { context = {
'object_list': cls.objects.all(), 'object_list': cls.objects.all(),
@@ -391,6 +396,9 @@ def setup_source_edit(request, source_type, source_id):
elif source_type == SOURCE_CHOICE_STAGING: elif source_type == SOURCE_CHOICE_STAGING:
cls = StagingFolder cls = StagingFolder
form_class = StagingFolderSetupForm form_class = StagingFolderSetupForm
elif source_type == SOURCE_CHOICE_WATCH:
cls = WatchFolder
form_class = WatchFolderSetupForm
source = get_object_or_404(cls, pk=source_id) source = get_object_or_404(cls, pk=source_id)
next = request.POST.get('next', request.GET.get('next', request.META.get('HTTP_REFERER', '/'))) next = request.POST.get('next', request.GET.get('next', request.META.get('HTTP_REFERER', '/')))
@@ -429,7 +437,11 @@ def setup_source_delete(request, source_type, source_id):
cls = StagingFolder cls = StagingFolder
form_icon = u'folder_delete.png' form_icon = u'folder_delete.png'
redirect_view = 'setup_staging_folder_list' redirect_view = 'setup_staging_folder_list'
elif source_type == SOURCE_CHOICE_WATCH:
cls = WatchFolder
form_icon = u'folder_delete.png'
redirect_view = 'setup_watch_folder_list'
redirect_view = reverse('setup_source_list', args=[source_type]) redirect_view = reverse('setup_source_list', args=[source_type])
previous = request.POST.get('previous', request.GET.get('previous', request.META.get('HTTP_REFERER', redirect_view))) previous = request.POST.get('previous', request.GET.get('previous', request.META.get('HTTP_REFERER', redirect_view)))
@@ -470,7 +482,10 @@ def setup_source_create(request, source_type):
elif source_type == SOURCE_CHOICE_STAGING: elif source_type == SOURCE_CHOICE_STAGING:
cls = StagingFolder cls = StagingFolder
form_class = StagingFolderSetupForm form_class = StagingFolderSetupForm
elif source_type == SOURCE_CHOICE_WATCH:
cls = WatchFolder
form_class = WatchFolderSetupForm
if request.method == 'POST': if request.method == 'POST':
form = form_class(data=request.POST) form = form_class(data=request.POST)
if form.is_valid(): if form.is_valid():
@@ -500,6 +515,8 @@ def setup_source_transformation_list(request, source_type, source_id):
cls = WebForm cls = WebForm
elif source_type == SOURCE_CHOICE_STAGING: elif source_type == SOURCE_CHOICE_STAGING:
cls = StagingFolder cls = StagingFolder
elif source_type == SOURCE_CHOICE_WATCH:
cls = WatchFolder
source = get_object_or_404(cls, pk=source_id) source = get_object_or_404(cls, pk=source_id)
@@ -597,7 +614,9 @@ def setup_source_transformation_create(request, source_type, source_id):
cls = WebForm cls = WebForm
elif source_type == SOURCE_CHOICE_STAGING: elif source_type == SOURCE_CHOICE_STAGING:
cls = StagingFolder cls = StagingFolder
elif source_type == SOURCE_CHOICE_WATCH:
cls = WatchFolder
source = get_object_or_404(cls, pk=source_id) source = get_object_or_404(cls, pk=source_id)
redirect_view = reverse('setup_source_transformation_list', args=[source.source_type, source.pk]) redirect_view = reverse('setup_source_transformation_list', args=[source.source_type, source.pk])

View File

@@ -0,0 +1,21 @@
if staging_folder.uncompress == SOURCE_UNCOMPRESS_CHOICE_Y:
expand = True
else:
expand = False
transformations, errors = SourceTransformation.transformations.get_for_object_as_list(staging_folder)
if (not expand) or (expand and not _handle_zip_file(request, staging_file.upload(), document_type=document_type, transformations=transformations)):
document = Document(file=staging_file.upload())
if document_type:
document.document_type = document_type
document.save()
document.apply_default_transformations(transformations)
_handle_save_document(request, document, form)
messages.success(request, _(u'Staging file: %s, uploaded successfully.') % staging_file.filename)
if staging_folder.delete_after_upload:
staging_file.delete(preview_size=staging_folder.get_preview_size(), transformations=transformations)
messages.success(request, _(u'Staging file: %s, deleted successfully.') % staging_file.filename)
except Exception, e:
messages.error(request, e)