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 %}
+
+ {% endif %}
+
+
+
+
+
+ {% if GEONODE_SECURITY_ENABLED %}
+
+
{% trans "Permissions" %}
+
+
+ {% 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('',