Table of Contents
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 components of ArcGIS Online such as WebMap functionality. In this post we will focus on adding Feature Layer search capabilities within the WebMap using teh ArcGIS API for Python.
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.
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 need to import the WebMap
class to create a WebMap
object. The WebMap
class is a part of the mapping
module. This mapping
module provides components for working with 2D and 3D maps and scenes. We also require the FeatureLayer
class from the features
module to access field information for the layers of our WebMap.
## import GIS which provides the gateway entry to your AGOL
from arcgis.gis import GIS
## import the WebMap class to provide for interacting with WebMap layers
from arcgis.mapping import WebMap
## import the FeatureLayer class to get field information
from arcgis.features import FeatureLayer
Accessing ArcGIS Online
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"
)
Access the WebMap via a WebMap Object
We can create a WebMap
object from an Item
object that represents a WebMap in ArcGIS Online. We use the ContentManager get()
method and supply in the WebMap item id. The get()
method returns an Item
object. We then use that WebMap Item
object and supply into our WebMap
class to create our WebMap
object.
## the ITEM ID of the WebMap to update
wm_item_id = "WM_ITEM_ID"
## get the WebMap as an Item object
wm_item = agol.content.get(wm_item_id)
## create a WebMap object from the Item object
webmap = WebMap(wm_item)
Prepare the Search configurations for each layer
We will see in the next section, that the “layers” property for the search application is a list, and it is a list of dictionaries.
Each dictionary contains an “id” key, which represents the id of the layer in the WebMap. We can obtain this “id” from the operationalLayers information for each layer.
Each dictionary also contains a “field” key, which has a dictionary value containing “name” (field name), “exactMatch” (we’ll set this to False so that the use does not have to enter the full search value), and “type” (field datatype – we are interested in Strings and Integers in this example).
I know my data and I know the I want Strings and Integer fields, you may only want Strings or you might know the exact field names you want to add to the search. You can alter the code here to suit your requirements.
Iterate through the layers in the WebMap and create a search entry for each field that matches the criteria.
## store a list of dictionaries, each dictionary will define the search for
## a field in a layer
search_layers = []
## iterate through the WebMap layers
for layer in webmap.definition.operationalLayers:
## create a FeatureLayer object
fl = FeatureLayer(
url = layer["url"],
gis = agol
)
## iterate through the fields for the Feature Layer
for fld in fl.properties.fields:
## if there are text of integer fields
if fld["type"] in ["esriFieldTypeString", "esriFieldTypeInteger"]:
## create an entry for the search_layers list
search_dict = {
"id" : layer["id"],
"field" : {
"name" : fld["name"],
"exactMatch": False,
"type" : fld["type"]
}
}
## add the dictionary to the list
search_layers.append(search_dict)
Alter the JSON to reflect the Search capabilities
A WebMap object can have an “applicationProperties” property in its definition. It is in here we want to add the properties that define our Search capabilities.
The search variable below, which is a dictionary, defines the Search capabilities for the WebMap. We set “enabled” to True, and the “layers” to the list of dictionaries we created in the previous section.
If there are currently no applications set on the WebMap then the “applicationProperties” property will more than likely not exists, and if so, we can add it ourselves and we will also make sure there is a “viewing” property within the “applicationProperties”.
It is to this “viewing” property that we want to add our Search definition.
## this is the JSON for the search capability with a WebMap
search = {
"enabled": True,
"disablePlaceFinder": False,
"hintText": "Search Here...",
"layers": search_layers,
"tables": []
}
## search is added to the viewing property of the applicationProperties property
## check if the applicationProperties currently exists and if it does not,
## define the property
if "applicationProperties" not in webmap.definition:
webmap.definition["applicationProperties"] = {"viewing" : {}}
## set the search property, within the viewing property to our search definition
## above
webmap.definition["applicationProperties"]["viewing"]["search"] = search
Update and Save the WebMap (item)
Because we have directly manipulated the JSON, we need to update the Item object that represents the WebMap and not the WebMap object itself. See the WebMap object versus WebMap Item blog post for more information on that!
item_properties = {"text":webmap.definition}
status = wm_item.update(
item_properties=item_properties
)
print(status)
Tip!
Add the search parameters manually and print the JSON to screen via the WebMap object definition property to see how the JSON is constructed.
Before and After Running the Script
Before
After
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.
## import GIS which provides the gateway entry to your AGOL
from arcgis.gis import GIS
## import the WebMap class to provide for interacting with WebMap layers
from arcgis.mapping import WebMap
## import the FeatureLayer class to get field information
from arcgis.features import FeatureLayer
################################################################################
## API Reference Links:
## https://developers.arcgis.com/python/api-reference/arcgis.gis.toc.html#gis
## https://developers.arcgis.com/python/api-reference/arcgis.gis.toc.html#arcgis.gis.ContentManager.get
## https://developers.arcgis.com/python/api-reference/arcgis.mapping.toc.html#webmap
## https://developers.arcgis.com/python/api-reference/arcgis.features.toc.html#featurelayer
## https://developers.arcgis.com/python/api-reference/arcgis.gis.toc.html#item
## https://developers.arcgis.com/python/api-reference/arcgis.gis.toc.html#arcgis.gis.Item.update
##
## API Version: 2.1.0.2, 2.2.0.1, 2.3.0
##
################################################################################
## Access AGOL
agol = GIS("home")
## Access the WebMap Item
wm_item = agol.content.get("WM_ITEM_ID")
## create a WebMap object from the WebMap Item object
webmap = WebMap(wm_item)
################################################################################
## CREATE SEARCH LAYERS DICTIONARIES ###########################################
## store a list of dictionaries, each dictionary will define the search for
## a field in a layer
search_layers = []
## iterate through the WebMap layers
for layer in webmap.definition.operationalLayers:
## create a FeatureLayer object
fl = FeatureLayer(
url = layer["url"],
gis = agol
)
## iterate through the fields for the Feature Layer
for fld in fl.properties.fields:
## if there are text of integer fields
if fld["type"] in ["esriFieldTypeString", "esriFieldTypeInteger"]:
## create an entry for the search_layers list
search_dict = {
"id" : layer["id"],
"field" : {
"name" : fld["name"],
"exactMatch": False,
"type" : fld["type"]
}
}
## add the dictionary to the list
search_layers.append(search_dict)
################################################################################
## MANIPULATE THE WEBMAP JSON ##################################################
## this is the JSON for the search capability with a WebMap
search = {
"enabled": True,
"disablePlaceFinder": False,
"hintText": "Search Here...",
"layers": search_layers,
"tables": []
}
## search is added to the viewing property of the applicationProperties property
## check if the applicationProperties currently exists and if it does not,
## define the property
if "applicationProperties" not in webmap.definition:
webmap.definition["applicationProperties"] = {"viewing" : {}}
## set the search property, within the viewing property to our search definition
## above
webmap.definition["applicationProperties"]["viewing"]["search"] = search
################################################################################
## UPDATE THE WEBMAP ITEM ######################################################
item_properties = {"text":webmap.definition}
status = wm_item.update(
item_properties=item_properties
)
print(status)
################################################################################
print("\nSCRIPT COMPLETE")