diff --git a/docs/tutorials/admin/admin_mgmt_commands/index.txt b/docs/tutorials/admin/admin_mgmt_commands/index.txt index 35bf9407795..e8a64205e2f 100644 --- a/docs/tutorials/admin/admin_mgmt_commands/index.txt +++ b/docs/tutorials/admin/admin_mgmt_commands/index.txt @@ -118,6 +118,57 @@ Additional options:: -h, --help show this help message and exit +createvectorlayer +================= + +Create an empty PostGIS vector layer in GeoNode. + +Usage:: + + python manage.py createvectorlayer name [options] + +Additional options:: + + manage.py createvectorlayer [-h] [--version] [-v {0,1,2,3}] + [--settings SETTINGS] + [--pythonpath PYTHONPATH] [--traceback] + [--no-color] [--user USER] + [--geometry GEOMETRY] + [--attributes ATTRIBUTES] [--title TITLE] + name + + Create an empty PostGIS vector layer in GeoNode. + + positional arguments: + name + + optional arguments: + -h, --help show this help message and exit + --version show program's version number and exit + -v {0,1,2,3}, --verbosity {0,1,2,3} + Verbosity level; 0=minimal output, 1=normal output, + 2=verbose output, 3=very verbose output + --settings SETTINGS The Python path to a settings module, e.g. + "myproject.settings.main". If this isn't provided, the + DJANGO_SETTINGS_MODULE environment variable will be + used. + --pythonpath PYTHONPATH + A directory to add to the Python path, e.g. + "/home/djangoprojects/myproject". + --traceback Raise on CommandError exceptions + --no-color Don't colorize the command output. + --user USER Name of the user account which should own the created + layer + --geometry GEOMETRY Geometry type of the layer to be created. Can be + Point, LineString or Polygon. Default is Point + --attributes ATTRIBUTES + A json representation of the attributes to create. + Example: { "field_str": "string", "field_int": + "integer", "field_date": "date", "field_float": + "float"} + --title TITLE Title for the layer to be created. + + fixsitename =========== diff --git a/docs/tutorials/users/managing_layers/create.txt b/docs/tutorials/users/managing_layers/create.txt new file mode 100644 index 00000000000..50b284694ea --- /dev/null +++ b/docs/tutorials/users/managing_layers/create.txt @@ -0,0 +1,22 @@ +.. _layers.create: + +Creating empty layers +===================== + +In GeoNode it is possible to create empty layers, that can be populated with features at a later stage using the mapping client editing tools. + +This is possible using the *createlayer* application, which can be enabled if GeoNode is installed with PostGIS. + +Once the application is enabled in GeoNode you will be able to create an empty layer by browsing to "Data > Create Layer". You will see a form like this: + +.. figure:: img/layer_create.png + +Fill the form as needed: + +* give a layer name +* give a layer title +* assign a geometry for the layer (Points, Lines, Polygons) +* add as many attributes as needed. For each attribute provide a name and a type. Type can be string, integer, float and date +* assign permissions as needed + +Now by clicking the "Create" button your new empty layer should be created. diff --git a/docs/tutorials/users/managing_layers/img/layer_create.png b/docs/tutorials/users/managing_layers/img/layer_create.png new file mode 100644 index 00000000000..6cc8989a67f Binary files /dev/null and b/docs/tutorials/users/managing_layers/img/layer_create.png differ diff --git a/docs/tutorials/users/managing_layers/index.txt b/docs/tutorials/users/managing_layers/index.txt index 89eac563903..62593e1d928 100644 --- a/docs/tutorials/users/managing_layers/index.txt +++ b/docs/tutorials/users/managing_layers/index.txt @@ -10,8 +10,8 @@ In this section, you will learn how to create a new layer by uploading a local d .. toctree:: :maxdepth: 2 - upload + upload info share more - + create diff --git a/geonode/contrib/createlayer/__init__.py b/geonode/contrib/createlayer/__init__.py new file mode 100644 index 00000000000..e69de29bb2d diff --git a/geonode/contrib/createlayer/forms.py b/geonode/contrib/createlayer/forms.py new file mode 100644 index 00000000000..d69d475043f --- /dev/null +++ b/geonode/contrib/createlayer/forms.py @@ -0,0 +1,51 @@ +# -*- coding: utf-8 -*- +######################################################################### +# +# Copyright (C) 2017 OSGeo +# +# This program is free software: you can redistribute it and/or modify +# it under the terms of the GNU General Public License as published by +# the Free Software Foundation, either version 3 of the License, or +# (at your option) any later version. +# +# This program is distributed in the hope that it will be useful, +# but WITHOUT ANY WARRANTY; without even the implied warranty of +# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +# GNU General Public License for more details. +# +# You should have received a copy of the GNU General Public License +# along with this program. If not, see . +# +######################################################################### + +from django import forms + + +GEOMETRY_TYPES = ( + ('Point', 'Points'), + ('LineString', 'Lines'), + ('Polygon', 'Polygons'), +) + + +class NewLayerForm(forms.Form): + """ + A form to create an empty layer in PostGIS. + """ + name = forms.CharField(label='Layer name', max_length=255) + title = forms.CharField(label='Layer title', max_length=255) + geometry_type = forms.ChoiceField(choices=GEOMETRY_TYPES) + + permissions = forms.CharField( + widget=forms.HiddenInput( + attrs={ + 'name': 'permissions', + 'id': 'permissions'}), + required=True) + + attributes = forms.CharField( + widget=forms.HiddenInput( + attrs={ + 'name': 'attributes', + 'id': 'attributes'}), + required=True) diff --git a/geonode/contrib/createlayer/management/__init__.py b/geonode/contrib/createlayer/management/__init__.py new file mode 100644 index 00000000000..e69de29bb2d diff --git a/geonode/contrib/createlayer/management/commands/__init__.py b/geonode/contrib/createlayer/management/commands/__init__.py new file mode 100644 index 00000000000..e69de29bb2d diff --git a/geonode/contrib/createlayer/management/commands/createvectorlayer.py b/geonode/contrib/createlayer/management/commands/createvectorlayer.py new file mode 100644 index 00000000000..8b8812e1374 --- /dev/null +++ b/geonode/contrib/createlayer/management/commands/createvectorlayer.py @@ -0,0 +1,59 @@ +# -*- coding: utf-8 -*- +######################################################################### +# +# Copyright (C) 2017 OSGeo +# +# This program is free software: you can redistribute it and/or modify +# it under the terms of the GNU General Public License as published by +# the Free Software Foundation, either version 3 of the License, or +# (at your option) any later version. +# +# This program is distributed in the hope that it will be useful, +# but WITHOUT ANY WARRANTY; without even the implied warranty of +# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +# GNU General Public License for more details. +# +# You should have received a copy of the GNU General Public License +# along with this program. If not, see . +# +######################################################################### + +from django.core.management.base import BaseCommand + +from geonode.people.utils import get_valid_user +from geonode.contrib.createlayer.utils import create_layer + + +class Command(BaseCommand): + help = "Create an empty PostGIS vector layer in GeoNode." + + def add_arguments(self, parser): + # positional arguments + parser.add_argument('name', type=str) + # named (optional arguments) + parser.add_argument('--user', + help='Name of the user account which should own the created layer') + parser.add_argument('--geometry', + default='Point', + help=('Geometry type of the layer to be created. ' + 'Can be Point, LineString or Polygon. Default is Point') + ) + parser.add_argument('--attributes', + help=('A json representation of the attributes to create. ' + 'Example: ' + '{ "field_str": "string", "field_int": "integer", ' + '"field_date": "date", "field_float": "float"}') + ) + parser.add_argument('--title', + default='No title', + help='Title for the layer to be created.' + ) + + def handle(self, *args, **options): + name = options.get('name') + username = options.get('user') + user = get_valid_user(username) + title = options.get('title') + geometry_type = options.get('geometry') + attributes = options.get('attributes') + create_layer(name, title, user, geometry_type, attributes) diff --git a/geonode/contrib/createlayer/templates/createlayer/layer_create.html b/geonode/contrib/createlayer/templates/createlayer/layer_create.html new file mode 100644 index 00000000000..f4c6abab7d0 --- /dev/null +++ b/geonode/contrib/createlayer/templates/createlayer/layer_create.html @@ -0,0 +1,112 @@ +{% extends "geonode_base.html" %} +{% load url from future %} +{% load i18n %} +{% load bootstrap_tags %} +{% load staticfiles %} + +{% block title %} {% trans "Create Layer" %} - {{ block.super }} {% endblock %} + +{% block body_class %}layer create{% endblock %} + + +{% block head %} + +{{ block.super }} +{% endblock %} + +{% block body_outer %} + + + +
+
+ + {% if error %} +
+

{{ error }}

+
+ {% endif %} + +
+
+ {% csrf_token %} + {{ form|as_bootstrap }} + +
+ +
+ + + +
+
+ +
+ + {% if GEONODE_SECURITY_ENABLED %} +
+

{% trans "Permissions" %}

+
+ {% include "_permissions.html" %} +
+
+ {% endif %} +
+{% endblock %} + + +{% block extra_script %} + +{{ block.super }} + +{% if GEONODE_SECURITY_ENABLED %} + {% include "_permissions_form_js.html" %} +{% endif %} + + + +{% endblock extra_script %} diff --git a/geonode/contrib/createlayer/tests.py b/geonode/contrib/createlayer/tests.py new file mode 100644 index 00000000000..1b1953526a1 --- /dev/null +++ b/geonode/contrib/createlayer/tests.py @@ -0,0 +1,169 @@ +# -*- coding: utf-8 -*- +######################################################################### +# +# Copyright (C) 2017 OSGeo +# +# This program is free software: you can redistribute it and/or modify +# it under the terms of the GNU General Public License as published by +# the Free Software Foundation, either version 3 of the License, or +# (at your option) any later version. +# +# This program is distributed in the hope that it will be useful, +# but WITHOUT ANY WARRANTY; without even the implied warranty of +# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +# GNU General Public License for more details. +# +# You should have received a copy of the GNU General Public License +# along with this program. If not, see . +# +######################################################################### + +import dj_database_url + +from django.conf import settings +from django.core.urlresolvers import reverse +from django.test import LiveServerTestCase as TestCase + +from geonode.geoserver.signals import gs_catalog +from geonode import GeoNodeException +from geonode.layers.models import Layer + +from .utils import create_layer + + +""" +How to run the tests +-------------------- + +Create a user and database for the datastore: + + $ sudo su postgres + $ psql + postgres=# CREATE USER geonode with password 'geonode'; + postgres=# ALTER USER geonode WITH LOGIN; + postgres=# ALTER USER geonode WITH SUPERUSER; + postgres=# CREATE DATABASE datastore WITH OWNER geonode; + postgres=# \c datastore + datastore=# CREATE EXTENSION postgis; + +Add 'geonode.contrib.createlayer' in GEONODE_CONTRIB_APPS + +Then, as usual, run "paver run_tests" + +""" + + +class CreateLayerCoreTest(TestCase): + + """ + Test createlayer application. + """ + + fixtures = ['initial_data.json', 'bobby'] + + def setUp(self): + # createlayer must use postgis as a datastore + # set temporary settings to use a postgis datastore + DATASTORE_URL = 'postgis://geonode:geonode@localhost:5432/datastore' + postgis_db = dj_database_url.parse(DATASTORE_URL, conn_max_age=600) + settings.DATABASES['datastore'] = postgis_db + settings.OGC_SERVER['default']['DATASTORE'] = 'datastore' + pass + + def tearDown(self): + # move to original settings + settings.OGC_SERVER['default']['DATASTORE'] = '' + del settings.DATABASES['datastore'] + # TODO remove stuff from django and geoserver catalog + pass + + def test_layer_creation_without_postgis(self): + # TODO implement this: must raise an error message + pass + + def test_layer_creation(self): + """ + Try creating a layer. + """ + + layer_name = 'point_layer' + layer_title = 'A layer for points' + + create_layer( + layer_name, + layer_title, + 'bobby', + 'Point' + ) + + cat = gs_catalog + + # Check the layer is in the Django database + layer = Layer.objects.get(name=layer_name) + + # check if it is in geoserver + gs_layer = cat.get_layer(layer_name) + self.assertIsNotNone(gs_layer) + self.assertEqual(gs_layer.name, layer_name) + + resource = gs_layer.resource + # we must have only one attibute ('the_geom') + self.assertEqual(len(resource.attributes), 1) + + # check layer corrispondence between django and geoserver + self.assertEqual(resource.title, layer_title) + self.assertEqual(resource.projection, layer.srid) + + # check if layer detail page is accessible with client + response = self.client.get(reverse('layer_detail', args=('geonode:%s' % layer_name,))) + self.assertEqual(response.status_code, 200) + + def test_layer_creation_with_wrong_geometry_type(self): + """ + Try creating a layer with uncorrect geometry type. + """ + with self.assertRaises(GeoNodeException): + create_layer( + 'wrong_geom_layer', + 'A layer with wrong geometry', + 'bobby', + 'wrong_geometry') + + def test_layer_creation_with_attributes(self): + """ + Try creating a layer with attributes. + """ + + attributes = """ + { + "field_str": "string", + "field_int": "integer", + "field_date": "date", + "field_float": "float" + } + """ + + layer_name = 'attributes_layer' + layer_title = 'A layer with attributes' + + create_layer( + layer_name, + layer_title, + 'bobby', + 'Point', + attributes + ) + + cat = gs_catalog + gs_layer = cat.get_layer(layer_name) + resource = gs_layer.resource + + # we must have one attibute for the geometry, and 4 other ones + self.assertEqual(len(resource.attributes), 5) + + def test_layer_creation_with_permissions(self): + """ + Try creating a layer with permissions. + """ + # TODO + pass diff --git a/geonode/contrib/createlayer/urls.py b/geonode/contrib/createlayer/urls.py new file mode 100644 index 00000000000..a3194797b42 --- /dev/null +++ b/geonode/contrib/createlayer/urls.py @@ -0,0 +1,26 @@ +# -*- coding: utf-8 -*- +######################################################################### +# +# Copyright (C) 2017 OSGeo +# +# This program is free software: you can redistribute it and/or modify +# it under the terms of the GNU General Public License as published by +# the Free Software Foundation, either version 3 of the License, or +# (at your option) any later version. +# +# This program is distributed in the hope that it will be useful, +# but WITHOUT ANY WARRANTY; without even the implied warranty of +# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +# GNU General Public License for more details. +# +# You should have received a copy of the GNU General Public License +# along with this program. If not, see . +# +######################################################################### + +from django.conf.urls import url +from . import views + +urlpatterns = [ + url(r'$', views.layer_create, name='layer_create') +] diff --git a/geonode/contrib/createlayer/utils.py b/geonode/contrib/createlayer/utils.py new file mode 100644 index 00000000000..d252a3e67d7 --- /dev/null +++ b/geonode/contrib/createlayer/utils.py @@ -0,0 +1,246 @@ +# -*- coding: utf-8 -*- +######################################################################### +# +# Copyright (C) 2017 OSGeo +# +# This program is free software: you can redistribute it and/or modify +# it under the terms of the GNU General Public License as published by +# the Free Software Foundation, either version 3 of the License, or +# (at your option) any later version. +# +# This program is distributed in the hope that it will be useful, +# but WITHOUT ANY WARRANTY; without even the implied warranty of +# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +# GNU General Public License for more details. +# +# You should have received a copy of the GNU General Public License +# along with this program. If not, see . +# +######################################################################### + +import requests +import uuid +import logging +import json + +from django.template.defaultfilters import slugify + +from geoserver.catalog import Catalog +from geoserver.catalog import FailedRequestError + +from geonode import GeoNodeException +from geonode.layers.models import Layer +from geonode.layers.utils import get_valid_name +from geonode.people.models import Profile +from geonode.geoserver.helpers import ogc_server_settings + + +logger = logging.getLogger(__name__) + + +def create_layer(name, title, owner_name, geometry_type, attributes=None): + """ + Create an empty layer in GeoServer and register it in GeoNode. + """ + # first validate parameters + if geometry_type not in ('Point', 'LineString', 'Polygon'): + msg = 'geometry must be Point, LineString or Polygon' + logger.error(msg) + raise GeoNodeException(msg) + name = get_valid_name(name) + # we can proceed + print 'Creating the layer in GeoServer' + workspace, datastore = create_gs_layer(name, title, geometry_type, attributes) + print 'Creating the layer in GeoNode' + return create_gn_layer(workspace, datastore, name, title, owner_name) + + +def create_gn_layer(workspace, datastore, name, title, owner_name): + """ + Associate a layer in GeoNode for a given layer in GeoServer. + """ + owner = Profile.objects.get(username=owner_name) + + layer = Layer.objects.create( + name=name, + workspace=workspace.name, + store=datastore.name, + storeType='dataStore', + alternate='%s:%s' % (workspace.name, name), + title=title, + owner=owner, + uuid=str(uuid.uuid4()), + bbox_x0=-180, + bbox_x1=180, + bbox_y0=-90, + bbox_y1=90 + ) + return layer + + +def get_attributes(geometry_type, json_attrs=None): + """ + Convert a json representation of attributes to a Python representation. + + parameters: + + json_attrs + { + "field_str": "string", + "field_int": "integer", + "field_date": "date", + "field_float": "float" + } + + geometry_type: a string which can be "Point", "LineString" or "Polygon" + + Output: + [ + ['the_geom', u'com.vividsolutions.jts.geom.Polygon', {'nillable': False}], + ['field_str', 'java.lang.String', {'nillable': True}], + ['field_int', 'java.lang.Integer', {'nillable': True}], + ['field_date', 'java.util.Date', {'nillable': True}], + ['field_float', 'java.lang.Float', {'nillable': True}] + ] + """ + + lattrs = [] + gattr = [] + gattr.append('the_geom') + gattr.append('com.vividsolutions.jts.geom.%s' % geometry_type) + gattr.append({'nillable': False}) + lattrs.append(gattr) + if json_attrs: + jattrs = json.loads(json_attrs) + for jattr in jattrs.items(): + lattr = [] + attr_name = slugify(jattr[0]) + attr_type = jattr[1].lower() + if len(attr_name) == 0: + msg = 'You must provide an attribute name for attribute of type %s' % (attr_type) + logger.error(msg) + raise GeoNodeException(msg) + if attr_type not in ('float', 'date', 'string', 'integer'): + msg = '%s is not a valid type for attribute %s' % (attr_type, attr_name) + logger.error(msg) + raise GeoNodeException(msg) + if attr_type == 'date': + attr_type = 'java.util.%s' % attr_type[:1].upper() + attr_type[1:] + else: + attr_type = 'java.lang.%s' % attr_type[:1].upper() + attr_type[1:] + lattr.append(attr_name) + lattr.append(attr_type) + lattr.append({'nillable': True}) + lattrs.append(lattr) + return lattrs + + +def get_or_create_datastore(cat, workspace=None, charset="UTF-8"): + """ + Get a PostGIS database store or create it in GeoServer if does not exist. + """ + + # TODO refactor this and geoserver.helpers._create_db_featurestore + dsname = ogc_server_settings.DATASTORE + if not ogc_server_settings.DATASTORE: + msg = ("To use the createlayer application you must set ogc_server_settings.datastore_db['ENGINE']" + " to 'django.contrib.gis.db.backends.postgis") + logger.error(msg) + raise GeoNodeException(msg) + + try: + ds = cat.get_store(dsname, workspace) + except FailedRequestError: + ds = cat.create_datastore(dsname, workspace=workspace) + + db = ogc_server_settings.datastore_db + ds.connection_parameters.update( + {'validate connections': 'true', + 'max connections': '10', + 'min connections': '1', + 'fetch size': '1000', + 'host': db['HOST'], + 'port': db['PORT'] if isinstance( + db['PORT'], basestring) else str(db['PORT']) or '5432', + 'database': db['NAME'], + 'user': db['USER'], + 'passwd': db['PASSWORD'], + 'dbtype': 'postgis'} + ) + + cat.save(ds) + + # we need to reload the ds as gsconfig-1.0.6 apparently does not populate ds.type + # using create_datastore (TODO fix this in gsconfig) + ds = cat.get_store(dsname, workspace) + + return ds + + +def create_gs_layer(name, title, geometry_type, attributes=None): + """ + Create an empty PostGIS layer in GeoServer with a given name, title, + geometry_type and attributes. + """ + + native_name = name + gs_user = ogc_server_settings.credentials[0] + gs_password = ogc_server_settings.credentials[1] + cat = Catalog(ogc_server_settings.internal_rest, gs_user, gs_password) + + # get workspace and store + workspace = cat.get_default_workspace() + + # get (or create the datastore) + datastore = get_or_create_datastore(cat, workspace) + + # check if datastore is of PostGIS type + if datastore.type != 'PostGIS': + msg = ("To use the createlayer application you must use PostGIS") + logger.error(msg) + raise GeoNodeException(msg) + + # check if layer is existing + resources = datastore.get_resources() + for resource in resources: + if resource.name == name: + msg = "There is already a layer named %s in %s" % (name, workspace) + logger.error(msg) + raise GeoNodeException(msg) + + attributes = get_attributes(geometry_type, attributes) + attributes_block = "" + for spec in attributes: + att_name, binding, opts = spec + nillable = opts.get("nillable", False) + attributes_block += ("" + "{name}" + "{binding}" + "{nillable}" + "").format(name=att_name, binding=binding, nillable=nillable) + attributes_block += "" + + # TODO implement others srs and not only EPSG:4326 + xml = ("" + "{name}" + "{native_name}" + "{title}" + "EPSG:4326" + "-180180-9090" + "EPSG:4326" + "{attributes}" + "").format( + name=name.encode('UTF-8', 'strict'), native_name=native_name.encode('UTF-8', 'strict'), + title=title.encode('UTF-8', 'strict'), + attributes=attributes_block) + + url = ('%s/workspaces/%s/datastores/%s/featuretypes' + % (ogc_server_settings.internal_rest, workspace.name, datastore.name)) + headers = {'Content-Type': 'application/xml'} + req = requests.post(url, data=xml, headers=headers, auth=(gs_user, gs_password)) + if req.status_code != 201: + logger.error('Request status code was: %s' % req.status_code) + logger.error('Response was: %s' % req.text) + raise GeoNodeException("Layer could not be created in GeoServer") + + return workspace, datastore diff --git a/geonode/contrib/createlayer/views.py b/geonode/contrib/createlayer/views.py new file mode 100644 index 00000000000..3e1ef412356 --- /dev/null +++ b/geonode/contrib/createlayer/views.py @@ -0,0 +1,63 @@ +# -*- coding: utf-8 -*- +######################################################################### +# +# Copyright (C) 2017 OSGeo +# +# This program is free software: you can redistribute it and/or modify +# it under the terms of the GNU General Public License as published by +# the Free Software Foundation, either version 3 of the License, or +# (at your option) any later version. +# +# This program is distributed in the hope that it will be useful, +# but WITHOUT ANY WARRANTY; without even the implied warranty of +# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +# GNU General Public License for more details. +# +# You should have received a copy of the GNU General Public License +# along with this program. If not, see . +# +######################################################################### + +import json + +from django.contrib.auth.decorators import login_required +from django.shortcuts import render_to_response +from django.template import RequestContext +from django.template.defaultfilters import slugify +from django.shortcuts import redirect + +from .forms import NewLayerForm +from .utils import create_layer + + +@login_required +def layer_create(request, template='createlayer/layer_create.html'): + """ + Create an empty layer. + """ + error = None + if request.method == 'POST': + form = NewLayerForm(request.POST) + if form.is_valid(): + try: + name = form.cleaned_data['name'] + name = slugify(name.replace(".", "_")) + title = form.cleaned_data['title'] + geometry_type = form.cleaned_data['geometry_type'] + attributes = form.cleaned_data['attributes'] + permissions = form.cleaned_data["permissions"] + layer = create_layer(name, title, request.user.username, geometry_type, attributes) + layer.set_permissions(json.loads(permissions)) + return redirect(layer) + except Exception as e: + error = '%s (%s)' % (e.message, type(e)) + else: + form = NewLayerForm() + + ctx = { + 'form': form, + 'is_layer': True, + 'error': error, + } + + return render_to_response(template, RequestContext(request, ctx)) diff --git a/geonode/settings.py b/geonode/settings.py index ac9ee78c389..1e5492dd425 100644 --- a/geonode/settings.py +++ b/geonode/settings.py @@ -94,6 +94,8 @@ ) ) +#DATABASE_URL = 'postgresql://test_geonode:test_geonode@localhost:5432/geonode' + # Defines settings for development DATABASES = { 'default': dj_database_url.parse(DATABASE_URL, conn_max_age=600) @@ -291,6 +293,7 @@ # 'geonode.contrib.geosites', # 'geonode.contrib.nlp', # 'geonode.contrib.slack', + #'geonode.contrib.createlayer', 'geonode.contrib.metadataxsl', 'geonode.contrib.api_basemaps', ) diff --git a/geonode/templates/base.html b/geonode/templates/base.html index 102b0afcc10..a411fae0c2b 100644 --- a/geonode/templates/base.html +++ b/geonode/templates/base.html @@ -66,6 +66,9 @@
  • {% trans "Remote Services" %}
  • Upload Layer
  • + {% if 'geonode.contrib.createlayer' in INSTALLED_APPS %} +
  • {% trans "Create Layer" %}
  • + {% endif %}
  • Upload Document
  • {% trans "Add Remote Service" %}
  • {% endif %} @@ -195,6 +198,9 @@

    You are using an outdated browser that is not supported by GeoNode.

    {% if user.is_authenticated %}
  • {% trans "Remote Services" %}
  • Upload Layer
  • + {% if 'geonode.contrib.createlayer' in INSTALLED_APPS %} +
  • {% trans "Create Layer" %}
  • + {% endif %}
  • Upload Document
  • {% trans "Add Remote Service" %}
  • {% endif %} diff --git a/geonode/urls.py b/geonode/urls.py index fb8e10473a5..618780248fe 100644 --- a/geonode/urls.py +++ b/geonode/urls.py @@ -129,6 +129,11 @@ (r'^showmetadata/', include('geonode.contrib.metadataxsl.urls')), ) +if "geonode.contrib.createlayer" in settings.INSTALLED_APPS: + urlpatterns += patterns('', + (r'^createlayer/', include('geonode.contrib.createlayer.urls')), + ) + if 'geonode.geoserver' in settings.INSTALLED_APPS: # GeoServer Helper Views urlpatterns += patterns('',