From 85455e76470555e3c8906d09f57648aa31ace3d5 Mon Sep 17 00:00:00 2001 From: Roberto Rosario Date: Tue, 16 Oct 2012 02:22:39 -0400 Subject: [PATCH] Add support for import bootstrap setups from URLs --- apps/bootstrap/classes.py | 4 ++-- apps/bootstrap/forms.py | 8 +++++++- apps/bootstrap/links.py | 3 ++- apps/bootstrap/managers.py | 19 +++++++++++++---- apps/bootstrap/post_init.py | 6 +++--- apps/bootstrap/urls.py | 3 ++- apps/bootstrap/views.py | 41 +++++++++++++++++++++++++++++-------- 7 files changed, 64 insertions(+), 20 deletions(-) diff --git a/apps/bootstrap/classes.py b/apps/bootstrap/classes.py index 0a83bdfe2b..f40230b017 100644 --- a/apps/bootstrap/classes.py +++ b/apps/bootstrap/classes.py @@ -139,7 +139,7 @@ class FixtureMetadata(object): single_result = instance.read_value(data) if single_result: result[instance.property_name] = single_result - + return result def __init__(self, literal, generate_function, read_function=None, property_name=None): @@ -160,4 +160,4 @@ class FixtureMetadata(object): for line in fixture_data.splitlines(False): if line.startswith(self.get_with_remark()): # TODO: replace the "+ 4" with a space and next character finding algo - return self.read_function(line[len(self.literal) + 4:]) + return self.read_function(line[len(self.literal) + 4:]) diff --git a/apps/bootstrap/forms.py b/apps/bootstrap/forms.py index 5314e8b6a5..30621a81a9 100644 --- a/apps/bootstrap/forms.py +++ b/apps/bootstrap/forms.py @@ -45,7 +45,13 @@ class BootstrapSetupForm_dump(BootstrapSetupForm): exclude = ('fixture',) -class BootstrapUploadForm(forms.Form): +class BootstrapFileImportForm(forms.Form): file = forms.FileField( label=_(u'Bootstrap setup file'), ) + + +class BootstrapURLImportForm(forms.Form): + url = forms.URLField( + label=_(u'Bootstrap setup URL'), + ) diff --git a/apps/bootstrap/links.py b/apps/bootstrap/links.py index 00bb4f57bf..4f15c4d24e 100644 --- a/apps/bootstrap/links.py +++ b/apps/bootstrap/links.py @@ -17,5 +17,6 @@ link_bootstrap_setup_view = {'text': _(u'details'), 'view': 'bootstrap_setup_vie link_bootstrap_setup_execute = {'text': _(u'execute'), 'view': 'bootstrap_setup_execute', 'args': 'object.pk', 'famfam': 'lightning_go', 'permissions': [PERMISSION_BOOTSTRAP_EXECUTE]} link_bootstrap_setup_dump = {'text': _(u'dump current setup'), 'view': 'bootstrap_setup_dump', 'famfam': 'arrow_down', 'permissions': [PERMISSION_BOOTSTRAP_DUMP]} link_bootstrap_setup_export = {'text': _(u'export'), 'view': 'bootstrap_setup_export', 'args': 'object.pk', 'famfam': 'disk', 'permissions': [PERMISSION_BOOTSTRAP_EXPORT]} -link_bootstrap_setup_import = {'text': _(u'import'), 'view': 'bootstrap_setup_import', 'famfam': 'folder', 'permissions': [PERMISSION_BOOTSTRAP_IMPORT]} +link_bootstrap_setup_import_from_file = {'text': _(u'import from file'), 'view': 'bootstrap_setup_import_from_file', 'famfam': 'folder', 'permissions': [PERMISSION_BOOTSTRAP_IMPORT]} +link_bootstrap_setup_import_from_url = {'text': _(u'import from URL'), 'view': 'bootstrap_setup_import_from_url', 'famfam': 'world', 'permissions': [PERMISSION_BOOTSTRAP_IMPORT]} link_erase_database = {'text': _(u'erase database'), 'view': 'erase_database_view', 'icon': 'radioactivity.png', 'permissions': [PERMISSION_NUKE_DATABASE]} diff --git a/apps/bootstrap/managers.py b/apps/bootstrap/managers.py index 69fc50f788..563fdaf112 100644 --- a/apps/bootstrap/managers.py +++ b/apps/bootstrap/managers.py @@ -2,11 +2,14 @@ from __future__ import absolute_import import logging +import requests + from django.db import models from django.core import serializers from .classes import BootstrapModel, FixtureMetadata -from .literals import FIXTURE_TYPE_FIXTURE_PROCESS, FIXTURE_TYPE_EMPTY_FIXTURE +from .literals import (FIXTURE_TYPE_FIXTURE_PROCESS, FIXTURE_TYPE_EMPTY_FIXTURE, + DEFAULT_REPOSITORY) logger = logging.getLogger(__name__) @@ -26,10 +29,18 @@ class BootstrapSetupManager(models.Manager): result.append(model_fixture) return FIXTURE_TYPE_FIXTURE_PROCESS[serialization_format]('\n'.join(result)) - def import_setup(self, files): - file_data = files.read() + def import_setup(self, file_data): metadata = FixtureMetadata.read_all(file_data) instance = self.model(fixture=file_data, **metadata) instance.save(update_metadata=False) + + def import_from_file(self, files): + file_data = files.read() + self.import_setup(file_data) - + def import_from_url(self, url): + response = requests.get(url) + if response.status_code == requests.codes.ok: + self.import_setup(response.text) + else: + response.raise_for_status() diff --git a/apps/bootstrap/post_init.py b/apps/bootstrap/post_init.py index e3e0d829a2..0e72128cc4 100644 --- a/apps/bootstrap/post_init.py +++ b/apps/bootstrap/post_init.py @@ -8,7 +8,7 @@ from main import __version__ from .links import (link_bootstrap_setup_create, link_bootstrap_setup_execute, link_bootstrap_setup_list, link_bootstrap_setup_edit, link_bootstrap_setup_delete, link_bootstrap_setup_view, link_bootstrap_setup_dump, link_bootstrap_setup_export, - link_bootstrap_setup_import) + link_bootstrap_setup_import_from_url, link_bootstrap_setup_import_from_file) from .models import BootstrapSetup from .classes import FixtureMetadata from .literals import (FIXTURE_METADATA_CREATED, FIXTURE_METADATA_EDITED, @@ -16,8 +16,8 @@ from .literals import (FIXTURE_METADATA_CREATED, FIXTURE_METADATA_EDITED, FIXTURE_METADATA_DESCRIPTION, DATETIME_STRING_FORMAT, FIXTURE_METADATA_SLUG) register_links([BootstrapSetup], [link_bootstrap_setup_view, link_bootstrap_setup_edit, link_bootstrap_setup_delete, link_bootstrap_setup_execute, link_bootstrap_setup_export]) -register_links([BootstrapSetup], [link_bootstrap_setup_list, link_bootstrap_setup_create, link_bootstrap_setup_dump, link_bootstrap_setup_import], menu_name='secondary_menu') -register_links(['bootstrap_setup_list', 'bootstrap_setup_create', 'bootstrap_setup_dump', 'bootstrap_setup_import'], [link_bootstrap_setup_list, link_bootstrap_setup_create, link_bootstrap_setup_dump, link_bootstrap_setup_import], menu_name='secondary_menu') +register_links([BootstrapSetup], [link_bootstrap_setup_list, link_bootstrap_setup_create, link_bootstrap_setup_dump, link_bootstrap_setup_import_from_file, link_bootstrap_setup_import_from_url], menu_name='secondary_menu') +register_links(['bootstrap_setup_list', 'bootstrap_setup_create', 'bootstrap_setup_dump', 'bootstrap_setup_import_from_file', 'bootstrap_setup_import_from_url'], [link_bootstrap_setup_list, link_bootstrap_setup_create, link_bootstrap_setup_dump, link_bootstrap_setup_import_from_file, link_bootstrap_setup_import_from_url], menu_name='secondary_menu') FixtureMetadata(FIXTURE_METADATA_CREATED, generate_function=lambda fixture_instance: fixture_instance.created.strftime(DATETIME_STRING_FORMAT), read_function=lambda x: datetime.datetime.strptime(x, DATETIME_STRING_FORMAT), property_name='created') FixtureMetadata(FIXTURE_METADATA_EDITED, generate_function=lambda fixture_instance: datetime.datetime.now().strftime(DATETIME_STRING_FORMAT)) diff --git a/apps/bootstrap/urls.py b/apps/bootstrap/urls.py index fb9a60890f..593ca5baf0 100644 --- a/apps/bootstrap/urls.py +++ b/apps/bootstrap/urls.py @@ -9,6 +9,7 @@ urlpatterns = patterns('bootstrap.views', url(r'^setup/(?P\d+)/execute/$', 'bootstrap_setup_execute', (), 'bootstrap_setup_execute'), url(r'^setup/(?P\d+)/export/$', 'bootstrap_setup_export', (), 'bootstrap_setup_export'), url(r'^setup/dump/$', 'bootstrap_setup_dump', (), 'bootstrap_setup_dump'), - url(r'^setup/import/$', 'bootstrap_setup_import', (), 'bootstrap_setup_import'), + url(r'^setup/import/file/$', 'bootstrap_setup_import_from_file', (), 'bootstrap_setup_import_from_file'), + url(r'^setup/import/url/$', 'bootstrap_setup_import_from_url', (), 'bootstrap_setup_import_from_url'), url(r'^nuke/$', 'erase_database_view', (), 'erase_database_view'), ) diff --git a/apps/bootstrap/views.py b/apps/bootstrap/views.py index 419958a7b0..569d16ae41 100644 --- a/apps/bootstrap/views.py +++ b/apps/bootstrap/views.py @@ -19,7 +19,7 @@ from .permissions import (PERMISSION_BOOTSTRAP_VIEW, PERMISSION_BOOTSTRAP_CREATE PERMISSION_BOOTSTRAP_EXECUTE, PERMISSION_NUKE_DATABASE, PERMISSION_BOOTSTRAP_DUMP, PERMISSION_BOOTSTRAP_EXPORT, PERMISSION_BOOTSTRAP_IMPORT) from .forms import (BootstrapSetupForm, BootstrapSetupForm_view, BootstrapSetupForm_dump, - BootstrapSetupForm_edit, BootstrapUploadForm) + BootstrapSetupForm_edit, BootstrapFileImportForm, BootstrapURLImportForm) from .exceptions import ExistingData @@ -227,32 +227,57 @@ def bootstrap_setup_export(request, bootstrap_setup_pk): ) -def bootstrap_setup_import(request): - +def bootstrap_setup_import_from_file(request): Permission.objects.check_permissions(request.user, [PERMISSION_BOOTSTRAP_IMPORT]) previous = request.POST.get('previous', request.GET.get('previous', request.META.get('HTTP_REFERER', '/'))) if request.method == 'POST': - form = BootstrapUploadForm(request.POST, request.FILES) + form = BootstrapFileImportForm(request.POST, request.FILES) if form.is_valid(): try: - BootstrapSetup.objects.import_setup(request.FILES['file']) + BootstrapSetup.objects.import_from_file(request.FILES['file']) messages.success(request, _(u'Bootstrap setup imported successfully.')) return HttpResponseRedirect(reverse('bootstrap_setup_list')) except Exception as exception: messages.error(request, exception) return HttpResponseRedirect(previous) else: - form = BootstrapUploadForm() + form = BootstrapFileImportForm() return render_to_response('generic_form.html', { - 'title': _(u'Import bootstrap setup'), + 'title': _(u'Import bootstrap setup from file'), 'form_icon': 'folder.png', 'form': form, 'previous': previous, }, context_instance=RequestContext(request)) - + + +def bootstrap_setup_import_from_url(request): + Permission.objects.check_permissions(request.user, [PERMISSION_BOOTSTRAP_IMPORT]) + + previous = request.POST.get('previous', request.GET.get('previous', request.META.get('HTTP_REFERER', '/'))) + + if request.method == 'POST': + form = BootstrapURLImportForm(request.POST, request.FILES) + if form.is_valid(): + try: + BootstrapSetup.objects.import_from_url(form.cleaned_data['url']) + messages.success(request, _(u'Bootstrap setup imported successfully.')) + return HttpResponseRedirect(reverse('bootstrap_setup_list')) + except Exception as exception: + messages.error(request, exception) + return HttpResponseRedirect(previous) + else: + form = BootstrapURLImportForm() + + return render_to_response('generic_form.html', { + 'title': _(u'Import bootstrap setup from URL'), + 'form_icon': 'folder.png', + 'form': form, + 'previous': previous, + }, context_instance=RequestContext(request)) + def erase_database_view(request): Permission.objects.check_permissions(request.user, [PERMISSION_NUKE_DATABASE])