Copy an ArcGIS Online Feature Layer from a Feature Service to Another with the ArcGIS API for Python

Table of Contents

Video

Introduction

The ArcGIS API for Python is a powerful Python library that allows users to interact with and automate tasks in ArcGIS Online (or Portal). The API is excellent for programmatically creating, maintaining, and updating Feature Services and Feature Layers in ArcGIS Online. In this post we will take a Feature Layer from one Feature Service and create/copy it in another Feature Service.

Unlock the full potential of ArcGIS Online by mastering the art of efficient Content Management with the ArcGIS API for Python. In this comprehensive course, you will embark on a journey to streamline your geospatial workflows, enhance data organization, and maximize the impact of your ArcGIS Online platform.

Geospatial Professionals, GIS Analysts, Data Managers, and enthusiasts will discover the power of automation and script-based operations to efficiently manage content in ArcGIS Online. Throughout this course, you will gain practical, hands-on experience in leveraging the ArcGIS API for Python to perform a wide range of content management tasks with ease.

arcgis modules

The API provides access to your organisations ArcGIS Online via the GIS class in the gis module. This GIS class is the gateway to ArcGIS Online. We will also import the FeatureLayerCollection class which represents a Feature Service in ArcGIS Online.

				
					## import GIS which provides the gateway entry to your AGOL
from arcgis.gis import GIS

## import FeatureLayerCollection from the features module
from arcgis.features import FeatureLayerCollection
				
			

Accessing ArcGIS Online

Our first port of call is to access your ArcGIS Online via the GIS class. There are a handful of ways to achieve access, if you are logged into your ArcGIS Online in ArcGIS Pro you can simply use "home", otherwise, another common way is to provide the ArcGIS Online URL, followed by your username and password.

				
					## Access AGOL
agol = GIS("home")
				
			
				
					## Access AGOL
agol = GIS(
    url = "https://your_organisation.maps.arcgis.com/",
    username = "Your_Username",
    password = "Your_Password"
)
				
			

User Input

We require three pieces of information from the user. The first is the Feature Layer name from the Feature Service that we want to copy from. We then need the content item IDs for the Feature Service that contains the layer to copy from, and the the Feature Service that we wish to create/copy the Feature Layer to.

				
					## The layer name from the Feature Service to add to the other Feature Service
layer_name = "FEATURE_LAYER_NAME"

## the Feature Service Item id that has the Feature Layer details
from_id = "FROM_FS_ITEM_ID"

## the Feature Service Item id where the FeatureLayer is being added
to_id = "TO_FS_ITEM_ID"
				
			

Get the Feature Layer Definition

We get the FeatureLayer object for the layer of interest and extract the properties (definition) as a dictionary.

				
					## Feature Service item where FeatureLayer details are
from_item = agol.content.get(from_id)

## get the FeatureLayer object
fl = [fl for fl in from_item.layers if fl.properties.name == layer_name][0]

## get the FeatureLayer properties as a dictionary
fl_definition = dict(fl.properties)
				
			

Tidy-up the Definition

We remove some of the properties and reset the relationships to an empty list. Relationships cause problems for some reason. The four properties that we delete will be added back in by ArcGIS Online.

				
					## delete some properties
del fl_definition["currentVersion"]
del fl_definition["id"]
del fl_definition["serviceItemId"]
del fl_definition["editingInfo"]

## remove any relationships
fl_definition["relationships"] = []
				
			

Update the Feature Service (FeatureLayerCollection)

We want to add the Feature Layer definition to the Feature Service. If we stopped here, the definition is added but the layer is not accessible yet.

				
					## Feature Service item to add FeatureLayer to
to_item = agol.content.get(to_id)

## Create a FeatureLayerCollection object from the Item object
flc = FeatureLayerCollection.fromitem(to_item)

## Update the JSON definition of the Service to include the layer
flc.manager.add_to_definition({"layers": [fl_definition]})
				
			

Update the Item Data

The hidden piece! In order for the layer to display in the Feature Service we need to update the text data (more JSON) behind the Feature Service. Here, we take a snippet of JSON from the original Item for the layer of interest, and append it to to the “layers” property in the Item we have added the layer to.

				
					## the JSON definition for the from
from_item_data = from_item.get_data()

## the JSON definition for the update
to_item_data = to_item.get_data()

## the FeatureLayer object for the from
from_fl = [fl for fl in from_item.layers if fl.properties.name == layer_name][0]

## the FetaureLayer object for the update
to_fl = [fl for fl in to_item.layers if fl.properties.name == layer_name][0]

## get the dictionary for the layer from the from
for lyr in from_item_data["layers"]:
    if lyr["id"] == from_fl.properties.id:
        update_dict = lyr
        ## update the id from the update
        update_dict["id"] = to_fl.properties.id


## revamp the "layers" property to include the added layer
current_layers = to_item_data["layers"]
new_layers = current_layers + [update_dict]
to_item_data["layers"] = new_layers

## update the JSON definition
item_properties = {"text" : to_item_data}

to_item.update(
    item_properties = item_properties
)
				
			

Append in the Data

Now all that there is left to do is to append in the data from the original Feature Service to the newly created Feature Layer.

				
					to_fl.append(
    item_id = from_id,
    upload_format = "featureService",
    source_table_name = layer_name
)
				
			

Geospatial Professionals, GIS Analysts, and enthusiasts will discover the power of automation and script-based operations to efficiently interact and update WebMaps in ArcGIS Online. Throughout this course, you will gain practical, hands-on experience in leveraging the ArcGIS API for Python to perform a wide range of WebMap tasks with ease.

We will dissect WebMaps for all that they are and by the end of this course you will be comfortable with manipulating the JSON, which is the behind the scenes configuration of a WebMap, to produce scripts for workflows where there is currently no API Python method, such as grouping layers.

All the code in one place

You can find the entire code workflow below with links to important components in the documentation that were used. Check out the video too!

				
					from arcgis.gis import GIS
from arcgis.features import FeatureLayerCollection

################################################################################
## API Documentatoion Links:
##  https://developers.arcgis.com/python/latest/api-reference/arcgis.gis.toc.html#gis
##  https://developers.arcgis.com/python/latest/api-reference/arcgis.gis.toc.html#arcgis.gis.ContentManager.get
##  https://developers.arcgis.com/python/latest/api-reference/arcgis.gis.toc.html#item
##  https://developers.arcgis.com/python/latest/api-reference/arcgis.features.toc.html#featurelayer
##  https://developers.arcgis.com/python/latest/api-reference/arcgis.features.toc.html#arcgis.features.FeatureLayer.properties
##  https://developers.arcgis.com/python/latest/api-reference/arcgis.gis.toc.html#arcgis.gis.Item.update
##  https://developers.arcgis.com/python/latest/api-reference/arcgis.features.toc.html#featurelayercollection
##  https://developers.arcgis.com/python/latest/api-reference/arcgis.features.toc.html#arcgis.features.FeatureLayerCollection.fromitem
##  https://developers.arcgis.com/python/latest/api-reference/arcgis.features.managers.html#arcgis.features.managers.FeatureLayerCollectionManager.update_definition
##  https://developers.arcgis.com/python/latest/api-reference/arcgis.features.toc.html#arcgis.features.FeatureLayer.append
##
################################################################################

## Access ArcGIS Online
agol = GIS("home")

################################################################################
## USER INPUT ##################################################################

## The layer name from the Feature Service to add to the other Feature Service
layer_name = "FEATURE_LAYER_NAME"

## the Feature Service Item id that has the Feature Layer details
from_id = "FROM_FS_ITEM_ID"

## the Feature Service Item id where the FeatureLayer is being added
to_id = "TO_FS_ITEM_ID"

################################################################################
## 1. GET FEATURELAYER DEFINITION ##############################################

## Feature Service item where FeatureLayer details are
from_item = agol.content.get(from_id)

## get the FeatureLayer object
fl = [fl for fl in from_item.layers if fl.properties.name == layer_name][0]

## get the FeatureLayer properties as a dictionary
fl_definition = dict(fl.properties)

## delete some properties
del fl_definition["currentVersion"]
del fl_definition["id"]
del fl_definition["serviceItemId"]
del fl_definition["editingInfo"]

## remove any relationships
fl_definition["relationships"] = []

################################################################################
## 2. ADD DEFINITION TO FEATURE SERVICE ########################################

## Feature Service item to add FeatureLayer to
to_item = agol.content.get(to_id)

## Create a FeatureLayerCollection object from the Item object
flc = FeatureLayerCollection.fromitem(to_item)

## Update the JSON definition of the Service to include the layer
flc.manager.add_to_definition({"layers": [fl_definition]})

################################################################################
## 3. UPDATE ITEM DATA #########################################################

## the JSON definition for the from
from_item_data = from_item.get_data()

## the JSON definition for the update
to_item_data = to_item.get_data()

## the FeatureLayer object for the from
from_fl = [fl for fl in from_item.layers if fl.properties.name == layer_name][0]

## the FetaureLayer object for the update
to_fl = [fl for fl in to_item.layers if fl.properties.name == layer_name][0]

## get the dictionary for the layer from the from
for lyr in from_item_data["layers"]:
    if lyr["id"] == from_fl.properties.id:
        update_dict = lyr
        ## update the id from the update
        update_dict["id"] = to_fl.properties.id


## revamp the "layers" property to include the added layer
current_layers = to_item_data["layers"]
new_layers = current_layers + [update_dict]
to_item_data["layers"] = new_layers

## update the JSON definition
item_properties = {"text" : to_item_data}

to_item.update(
    item_properties = item_properties
)

################################################################################
## 4. APPEND DATA ##############################################################

to_fl.append(
    item_id = from_id,
    upload_format = "featureService",
    source_table_name = layer_name
)

################################################################################
print("\nSCRIPT COMPLETE")
				
			

Leave a Comment

Your email address will not be published. Required fields are marked *