Skip to content
Merged
Show file tree
Hide file tree
Changes from 9 commits
Commits
Show all changes
30 commits
Select commit Hold shift + click to select a range
5a77a22
blank dataset handler
mattiagiupponi Oct 6, 2025
5d570ca
[Fixes #13507] Create dataset page moved to the importer
mattiagiupponi Oct 7, 2025
f1a8284
Fixes #13507: add additional kwarg for publisher
mattiagiupponi Oct 8, 2025
bae4bbd
Fixes #13507: add handler for empty dataset
mattiagiupponi Oct 8, 2025
80fdf32
Fixes #13507: add handler for empty dataset
mattiagiupponi Oct 8, 2025
957e251
Fixes #13507: add handler for empty dataset
mattiagiupponi Oct 8, 2025
6e4d3a8
Fixes #13507: minor typos fix and remove legacy code
mattiagiupponi Oct 8, 2025
3ce8770
Fixes #13507: minor typos fix and remove legacy code
mattiagiupponi Oct 8, 2025
45af87d
[Fixes #13507] merge with master
mattiagiupponi Oct 10, 2025
9f8a118
[Fixes #13507] Add test coverage for empty dataset
mattiagiupponi Oct 10, 2025
fb34d33
[Fixes #13507] Add test coverage for empty dataset
mattiagiupponi Oct 10, 2025
27132d5
[Fixes #13507] Add test coverage for empty dataset
mattiagiupponi Oct 10, 2025
e97b1bb
[Fixes #13507] Add test coverage for empty dataset
mattiagiupponi Oct 10, 2025
7b0cbe0
[Fixes #13507] Add test coverage for empty dataset
mattiagiupponi Oct 10, 2025
68ee9fa
[Fixes #13507] fix empty dataset when attributes are not defined
mattiagiupponi Oct 13, 2025
3b2b02e
Add base image with gdal upgrade
mattiagiupponi Oct 13, 2025
5970ead
Merge branch 'master' of github.com:GeoNode/geonode into ISSUE_13507
mattiagiupponi Oct 15, 2025
a1f55e3
[Fixes #13507] thumbnail as optiona and fix attribute for attributes …
mattiagiupponi Oct 15, 2025
e5f56f8
[Fixes #13507] thumbnail as optiona and fix attribute for attributes …
mattiagiupponi Oct 15, 2025
2194988
[Fixes #13507] remove unwanted changes
mattiagiupponi Oct 15, 2025
064b2ff
Merge branch 'master' of github.com:GeoNode/geonode into ISSUE_13507
mattiagiupponi Oct 17, 2025
4e7ffd8
[Fixes #13507] Create dataset page moved to the importer
mattiagiupponi Oct 17, 2025
5b3ec06
[Fixes #13507] Create dataset page moved to the importer
mattiagiupponi Oct 17, 2025
273bfff
[Fixes #13507] Create dataset page moved to the importer
mattiagiupponi Oct 17, 2025
f7ff382
[Fixes #13507] Create dataset page moved to the importer
mattiagiupponi Oct 20, 2025
21dccd5
Merge branch 'master' of github.com:GeoNode/geonode into ISSUE_13507
mattiagiupponi Oct 21, 2025
8841ea1
[Fixes #13507] align test docker to latest ubuntu version
mattiagiupponi Oct 21, 2025
d970261
[Fixes #13507] test fix test
mattiagiupponi Oct 21, 2025
566193b
merge with master
mattiagiupponi Oct 28, 2025
dc85f5a
merge with master
mattiagiupponi Oct 28, 2025
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
2 changes: 1 addition & 1 deletion .env_dev
Original file line number Diff line number Diff line change
Expand Up @@ -39,7 +39,7 @@ GEONODE_DB_CONN_TOUT=5
DEFAULT_BACKEND_DATASTORE=datastore
BROKER_URL=redis://localhost:6379/0
CELERY_BEAT_SCHEDULER=celery.beat:PersistentScheduler
ASYNC_SIGNALS=False
ASYNC_SIGNALS=True

SITEURL=http://localhost:8000/

Expand Down
45 changes: 0 additions & 45 deletions geonode/geoserver/createlayer/forms.py

This file was deleted.

5 changes: 0 additions & 5 deletions geonode/geoserver/createlayer/urls.py
Original file line number Diff line number Diff line change
Expand Up @@ -16,8 +16,3 @@
# along with this program. If not, see <http://www.gnu.org/licenses/>.
#
#########################################################################

from django.urls import re_path
from . import views

urlpatterns = [re_path(r"$", views.dataset_create, name="dataset_create")]
63 changes: 0 additions & 63 deletions geonode/geoserver/createlayer/views.py

This file was deleted.

2 changes: 1 addition & 1 deletion geonode/upload/api/views.py
Original file line number Diff line number Diff line change
Expand Up @@ -149,7 +149,7 @@ def create(self, request, *args, **kwargs):
}

# clone the memory files into local file system
if "url" not in _data:
if "url" not in _data and not _data.get("is_empty", False):
storage_manager = StorageManager(
remote_files={k: v for k, v in _data.items() if k.endswith("_file")},
concrete_storage_manager=FileSystemStorageManager(),
Expand Down
17 changes: 13 additions & 4 deletions geonode/upload/celery_tasks.py
Original file line number Diff line number Diff line change
Expand Up @@ -367,7 +367,7 @@ def publish_resource(
_overwrite = _exec.input_params.get("overwrite_existing_layer")

_publisher = DataPublisher(handler_module_path)

kwargs.update({"exec_id": execution_id})
# extracting the crs and the resource name, are needed for publish the resource
data = _publisher.extract_resource_to_publish(_files, action, layer_name, alternate, **kwargs)
if data:
Expand Down Expand Up @@ -714,10 +714,19 @@ def _create_field(dynamic_model_schema, field, _kwargs):
row_to_insert.append(_create_field(dynamic_model_schema, field, _kwargs))

if row_to_insert:
# the build creation improves the overall permformance with the DB
FieldSchema.objects.bulk_create(row_to_insert, 30)
if dynamic_model_schema.managed:
# we have to loop in order to generate the schema of the table
for field in row_to_insert:
if field.name == "fid":
with connections[os.getenv("DEFAULT_BACKEND_DATASTORE", "datastore")].cursor() as cursor:
cursor.execute(f"ALTER TABLE {dynamic_model_schema.name} RENAME COLUMN id TO fid;")
else:
field.save()
else:
# the build creation improves the overall permformance with the DB
FieldSchema.objects.bulk_create(row_to_insert, 30)
# fixing the schema model in django

del row_to_insert
return "dynamic_model", layer_name, execution_id


Expand Down
4 changes: 1 addition & 3 deletions geonode/upload/datastore.py
Original file line number Diff line number Diff line change
Expand Up @@ -44,12 +44,10 @@ def input_is_valid(self):
"""
Perform basic validation steps
"""
if self.files:
return self.handler.is_valid(self.files, self.user, execution_id=self.execution_id)
url = orchestrator.get_execution_object(exec_id=self.execution_id).input_params.get("url")
if url:
return self.handler.is_valid_url(url)
return False
return self.handler.is_valid(self.files, self.user, execution_id=self.execution_id)

def _import_and_register(self, execution_id, task_name, **kwargs):
"""
Expand Down
2 changes: 1 addition & 1 deletion geonode/upload/handlers/README.md
Original file line number Diff line number Diff line change
Expand Up @@ -99,7 +99,7 @@ class BaseVectorFileHandler(BaseHandler):
return

@staticmethod
def create_ogr2ogr_command(files, original_name, ovverwrite_layer, alternate):
def create_ogr2ogr_command(files, original_name, ovverwrite_layer, alternate, **kwargs):
"""
Define the ogr2ogr command to be executed.
This is a default command that is needed to import a vector file. For Raster file
Expand Down
55 changes: 33 additions & 22 deletions geonode/upload/handlers/common/vector.py
Original file line number Diff line number Diff line change
Expand Up @@ -245,7 +245,7 @@ def _delete_resource(self, resource, catalog, workspace):
catalog.delete(res, purge="all", recurse=True)

@staticmethod
def create_ogr2ogr_command(files, original_name, ovverwrite_layer, alternate):
def create_ogr2ogr_command(files, original_name, ovverwrite_layer, alternate, **kwargs):
"""
Define the ogr2ogr command to be executed.
This is a default command that is needed to import a vector file
Expand Down Expand Up @@ -554,7 +554,10 @@ def setup_dynamic_model(
- celery_group -> the celery group of the field creation
"""

layer_name = self.fixup_name(layer.GetName())
layer_name = self.fixup_name(layer.GetName() if isinstance(layer, ogr.Layer) else layer)
is_dynamic_model_managed = orchestrator.get_execution_object(execution_id).input_params.get(
"is_dynamic_model_managed", False
)
workspace = DataPublisher(None).workspace
user_datasets = Dataset.objects.filter(owner=username, alternate__iexact=f"{workspace.name}:{layer_name}")
dynamic_schema = ModelSchema.objects.filter(name__iexact=layer_name)
Expand All @@ -577,7 +580,7 @@ def setup_dynamic_model(
dynamic_schema = ModelSchema.objects.create(
name=layer_name,
db_name="datastore",
managed=False,
managed=is_dynamic_model_managed,
db_table_name=layer_name,
)
elif (
Expand All @@ -593,7 +596,7 @@ def setup_dynamic_model(
dynamic_schema, _ = ModelSchema.objects.get_or_create(
name=layer_name,
db_name="datastore",
managed=False,
managed=is_dynamic_model_managed,
db_table_name=layer_name,
)
else:
Expand All @@ -619,6 +622,26 @@ def create_dynamic_model_fields(
return_celery_group: bool = True,
):
# retrieving the field schema from ogr2ogr and converting the type to Django Types

layer_schema = self._define_dynamic_layer_schema(layer, execution_id=execution_id)

if not return_celery_group:
return layer_schema

# ones we have the schema, here we create a list of chunked value
# so the async task will handle max of 30 field per task
list_chunked = [layer_schema[i : i + 30] for i in range(0, len(layer_schema), 30)] # noqa

# definition of the celery group needed to run the async workflow.
# in this way each task of the group will handle only 30 field
celery_group = group(
create_dynamic_structure.s(execution_id, schema, dynamic_model_schema.id, overwrite, layer_name)
for schema in list_chunked
)

return dynamic_model_schema, celery_group

def _define_dynamic_layer_schema(self, layer, **kwargs):
layer_schema = [
{"name": self.fixup_name(x.name), "class_name": self._get_type(x), "null": True} for x in layer.schema
]
Expand All @@ -639,21 +662,7 @@ def create_dynamic_model_fields(
}
]

if not return_celery_group:
return layer_schema

# ones we have the schema, here we create a list of chunked value
# so the async task will handle max of 30 field per task
list_chunked = [layer_schema[i : i + 30] for i in range(0, len(layer_schema), 30)] # noqa

# definition of the celery group needed to run the async workflow.
# in this way each task of the group will handle only 30 field
celery_group = group(
create_dynamic_structure.s(execution_id, schema, dynamic_model_schema.id, overwrite, layer_name)
for schema in list_chunked
)

return dynamic_model_schema, celery_group
return layer_schema

def promote_to_multi(self, geometry_name: str):
"""
Expand Down Expand Up @@ -736,13 +745,15 @@ def create_geonode_resource(
# getting the relative model schema
schema = ModelSchema.objects.filter(name=table_name).first()
# creating the field needed as primary key
schema.managed = False
pk_field = FieldSchema(
name=column[0],
model_schema=schema,
class_name="django.db.models.BigAutoField",
kwargs={"null": False, "primary_key": True},
)
pk_field.save()
schema.save()

return saved_dataset

Expand Down Expand Up @@ -1354,15 +1365,15 @@ def import_next_step(
actual_step,
layer_name,
alternate,
exa.UPLOAD.value,
_exec.input_params.get("action", exa.UPLOAD.value),
)

import_orchestrator.apply_async(task_params, kwargs)
except Exception as e:
call_rollback_function(
execution_id,
handlers_module_path=handlers_module_path,
prev_action=exa.UPLOAD.value,
prev_action=_exec.input_params.get("action", exa.UPLOAD.value),
layer=layer_name,
alternate=alternate,
error=e,
Expand Down Expand Up @@ -1398,7 +1409,7 @@ def import_with_ogr2ogr(
ogr_exe = "/usr/bin/ogr2ogr"

options = orchestrator.load_handler(handler_module_path).create_ogr2ogr_command(
files, original_name, ovverwrite_layer, alternate
files, original_name, ovverwrite_layer, alternate, execution_id=execution_id
)
_datastore = settings.DATABASES["datastore"]

Expand Down
2 changes: 1 addition & 1 deletion geonode/upload/handlers/csv/handler.py
Original file line number Diff line number Diff line change
Expand Up @@ -124,7 +124,7 @@ def get_ogr2ogr_driver(self):
return ogr.GetDriverByName("CSV")

@staticmethod
def create_ogr2ogr_command(files, original_name, ovverwrite_layer, alternate):
def create_ogr2ogr_command(files, original_name, ovverwrite_layer, alternate, **kwargs):
"""
Define the ogr2ogr command to be executed.
This is a default command that is needed to import a vector file
Expand Down
18 changes: 18 additions & 0 deletions geonode/upload/handlers/empty_dataset/__init__.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,18 @@
#########################################################################
#
# Copyright (C) 2025 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 <http://www.gnu.org/licenses/>.
#
#########################################################################
Loading
Loading