@@ -455,7 +455,7 @@ def import_resource(self, files: dict, execution_id: str, **kwargs) -> str:
455455 data inside the geonode_data database
456456 """
457457 all_layers = self .get_ogr2ogr_driver ().Open (files .get ("base_file" ))
458- layers = self ._select_valid_layers (all_layers )
458+ layers = self ._select_valid_layers (all_layers , execution_id = execution_id )
459459 # for the moment we skip the dyanamic model creation
460460 layer_count = len (layers )
461461 logger .info (f"Total number of layers available: { layer_count } " )
@@ -556,7 +556,7 @@ def import_resource(self, files: dict, execution_id: str, **kwargs) -> str:
556556 raise e
557557 return layer_names , alternates , execution_id
558558
559- def _select_valid_layers (self , all_layers ):
559+ def _select_valid_layers (self , all_layers , ** kwargs ):
560560 layers = []
561561 for layer in all_layers :
562562 try :
@@ -738,7 +738,17 @@ def _define_dynamic_layer_schema(self, layer, **kwargs):
738738 "authority" : self .identify_authority (layer ),
739739 }
740740 ]
741-
741+ # if the layer comes from a DB, the fid column is not included in the schema, but we need to add it as primary key for the dynamic model
742+ fid_in_schema = any (x ["name" ] == DEFAULT_PK_COLUMN_NAME for x in layer_schema )
743+ if not fid_in_schema and layer .GetFIDColumn ():
744+ layer_schema += [
745+ {
746+ "name" : layer .GetFIDColumn (),
747+ "class_name" : "django.db.models.BigAutoField" ,
748+ "null" : False ,
749+ "primary_key" : True ,
750+ }
751+ ]
742752 return layer_schema
743753
744754 def promote_to_multi (self , geometry_name ):
@@ -1129,7 +1139,7 @@ def __get_new_and_original_schema(self, files, execution_id):
11291139
11301140 # use ogr2ogr to read the uploaded files for the upsert
11311141 all_layers = self .get_ogr2ogr_driver ().Open (files .get ("base_file" ))
1132- layers = self ._select_valid_layers (all_layers )
1142+ layers = self ._select_valid_layers (all_layers , execution_id = execution_id )
11331143 if not layers :
11341144 raise UpsertException ("No valid layers found in the provided file for upsert." )
11351145
@@ -1213,20 +1223,20 @@ def upsert_data(self, files, execution_id, **kwargs):
12131223 # get the rows that match the upsert key
12141224 OriginalResource = model .as_model ()
12151225
1216- # retrieve the upsert key.
1217- upsert_key = self .extract_upsert_key (exec_obj , dynamic_model_instance = model )
1218- if not upsert_key :
1219- # if for any reason the key is not present, better to raise an error
1220- raise UpsertException ("Was not possible to find the upsert key, upsert is aborted" )
12211226 # use ogr2ogr to read the uploaded files values for the upsert
12221227 all_layers = self .get_ogr2ogr_driver ().Open (files .get ("base_file" ))
12231228 valid_create = 0
12241229 valid_update = 0
1225- layers = self ._select_valid_layers (all_layers )
1230+ layers = self ._select_valid_layers (all_layers , execution_id = execution_id )
12261231 if not layers :
12271232 raise UpsertException ("No valid layers were found in the file provided" )
12281233 # we can upsert just 1 layer at time
12291234
1235+ upsert_key = self .extract_upsert_key (layers [0 ])
1236+ if not upsert_key :
1237+ # if for any reason the key is not present, better to raise an error
1238+ raise UpsertException ("Was not possible to find the upsert key, upsert is aborted" )
1239+
12301240 self ._validate_single_feature (exec_obj , OriginalResource , upsert_key , layers , iter (layers [0 ]))
12311241
12321242 valid_create , valid_update = self ._commit_upsert (model , OriginalResource , upsert_key , iter (layers [0 ]))
@@ -1359,9 +1369,16 @@ def _validate_feature(self, data_chunk, model_instance, upsert_key, errors):
13591369 def _save_feature (self , data_chunk , model_obj , model_instance , upsert_key , valid_update , valid_create ):
13601370 # getting all the upsert_key value from the data chunk
13611371 # retrieving the data from the DB
1362- value_in_db = model_instance .objects .filter (
1363- ** {f"{ upsert_key } __in" : (getattr (feature , upsert_key ) for feature in data_chunk )}
1364- ).in_bulk (field_name = upsert_key )
1372+ use_get_fid = False # flag to understand if we need to use the GetFID as upsert key, this is needed for DB drivers with FID columns that hide the FID field from the schema
1373+ filters = []
1374+ for feature in data_chunk :
1375+ # DB drivers with FID columns hide the FID field from the schema, so we need to check if the FID is present and use it as upsert key if the upsert key is the default one
1376+ if not getattr (feature , upsert_key , None ) and feature .GetFID () != ogr .NullFID :
1377+ filters .append (feature .GetFID ())
1378+ use_get_fid = True
1379+ else :
1380+ filters .append (getattr (feature , upsert_key ))
1381+ value_in_db = model_instance .objects .filter (** {f"{ upsert_key } __in" : filters }).in_bulk (field_name = upsert_key )
13651382 # looping over the chunk data
13661383 to_process = []
13671384 feature_to_save = []
@@ -1384,6 +1401,8 @@ def _save_feature(self, data_chunk, model_obj, model_instance, upsert_key, valid
13841401 feature_as_dict .update (
13851402 {self .default_geometry_column_name : f"SRID={ code } ;{ self .promote_geom_to_multi (geom ).ExportToWkt ()} " }
13861403 )
1404+ if use_get_fid :
1405+ feature_as_dict [upsert_key ] = feature .GetFID ()
13871406 to_process .append (feature_as_dict )
13881407
13891408 for feature_as_dict in to_process :
@@ -1419,18 +1438,13 @@ def validate_feature(self, feature):
14191438 feature ["error" ] = " | " .join (errors )
14201439 return feature , False
14211440
1422- def extract_upsert_key (self , exec_obj , dynamic_model_instance ):
1423- # first we check if the upsert key is passed by the call
1424- key = exec_obj .input_params .get ("upsert_key" , DEFAULT_PK_COLUMN_NAME )
1425- if not key :
1426- # if the upsert key is not passed, we use the primary key as upsert key
1427- # the primary key is defined in the Fields of the dynamic model
1428- # dynamic models raise error if we filter the json with ORM
1429- key = [x .name for x in dynamic_model_instance .fields .all () if x .kwargs .get ("primary_key" )]
1430- if key :
1431- return key [0 ]
1441+ def extract_upsert_key (self , layer ):
14321442
1433- return key
1443+ fid_in_schema = any (x .name == DEFAULT_PK_COLUMN_NAME for x in layer .schema )
1444+ if not fid_in_schema and layer .GetFIDColumn ():
1445+ return layer .GetFIDColumn ()
1446+
1447+ return DEFAULT_PK_COLUMN_NAME
14341448
14351449 def refresh_geonode_resource (self , execution_id , asset = None , dataset = None , create_asset = True , ** kwargs ):
14361450 # getting execution_id information
@@ -1485,7 +1499,6 @@ def fixup_dynamic_model_fields(self, _exec, files, **kwargs):
14851499 self .__fixup_primary_key (dataset )
14861500
14871501
1488-
14891502@importer_app .task (
14901503 base = ErrorBaseTaskClass ,
14911504 name = "geonode.upload.import_next_step" ,
0 commit comments