Hi there,
I am trying to programmatically change the Visibility Range of layers published to the Enterprise Portal. It is possible to do this manually (as shown below), yet that is not the preferred option as I have to adjust a large amount of layers.
When having a look at the Python API I did not find a method which would be able to do that. Any help in this matter would be highly appreciated.
I have also been looking through GeoNet and came across similar questions (See https://community.esri.com/thread/241752-setting-visibility-scale-using-the-arcgis-api-for-python, https://community.esri.com/thread/192664-set-visibility-range-andor-add-filter-using-arcgis-python-a...), yet I did not find the answer there.
Solved! Go to Solution.
Accidently anwered the linked issue but lets copy it here as well.
Here is one way how you can do that for one service and it could give you idea how to implement the full process.
EDIT: Note that I understood that you want to change the range in the Feature Service level (and not override it later on the configuration stack ie. WebMap level).
from arcgis.gis import GIS
import getpass
password = getpass.getpass("Enter password: ")
gis = GIS('https://cgisuomi.maps.arcgis.com/home', 'antti.kajanus_CGISuomi', password)
print("Connected to: {}".format(gis.properties.urlKey + "." + gis.properties.customBaseUrl))
print("Connected as: {}".format(gis.users.me.username))
from arcgis.features import FeatureLayer
feature_layer = feature_layer_item.layers[0]
feature_layer
#<FeatureLayer url:"https://services1.arcgis.com/ut5Ig3pyAO7DhCxU/arcgis/rest/services/HSLCityBikes/FeatureServer/0">
import requests
import json
# Get service content info
request = requests.get(feature_layer.url + '?f=pjson&token={}'.format(gis._con.token))
service_layer_json = request.json()
#Check current scale range
print('MinScale = {}'.format(service_layer_json['minScale']))
print('MaxScale = {}'.format(service_layer_json['maxScale']))
# MinScale = 1155582
# MaxScale = 0
#Update scale range
service_layer_json['minScale'] = 15000
service_layer_json['maxScale'] = 150
#Check new scale range
print('MinScale = {}'.format(service_layer_json['minScale']))
print('MaxScale = {}'.format(service_layer_json['maxScale']))
# MinScale = 15000
# MaxScale = 150
# Apply edits to the service
# Make sure that url is not in the properties
if 'editingInfo' in service_layer_json:
del service_layer_json['editingInfo']
result = feature_layer.manager.update_definition(service_layer_json)
result
# {'success': True}
# Testing that changes have been applied
feature_layer_item = gis.content.get('96d90824c0b94025abefeb7fe0ef60a0')
# Get service content info
request = requests.get(feature_layer.url + '?f=pjson&token={}'.format(gis._con.token))
service_layer_json = request.json()
#Check current scale range
print('MinScale = {}'.format(service_layer_json['minScale']))
print('MaxScale = {}'.format(service_layer_json['maxScale']))
# MinScale = 15000
# MaxScale = 150
Accidently anwered the linked issue but lets copy it here as well.
Here is one way how you can do that for one service and it could give you idea how to implement the full process.
EDIT: Note that I understood that you want to change the range in the Feature Service level (and not override it later on the configuration stack ie. WebMap level).
from arcgis.gis import GIS
import getpass
password = getpass.getpass("Enter password: ")
gis = GIS('https://cgisuomi.maps.arcgis.com/home', 'antti.kajanus_CGISuomi', password)
print("Connected to: {}".format(gis.properties.urlKey + "." + gis.properties.customBaseUrl))
print("Connected as: {}".format(gis.users.me.username))
from arcgis.features import FeatureLayer
feature_layer = feature_layer_item.layers[0]
feature_layer
#<FeatureLayer url:"https://services1.arcgis.com/ut5Ig3pyAO7DhCxU/arcgis/rest/services/HSLCityBikes/FeatureServer/0">
import requests
import json
# Get service content info
request = requests.get(feature_layer.url + '?f=pjson&token={}'.format(gis._con.token))
service_layer_json = request.json()
#Check current scale range
print('MinScale = {}'.format(service_layer_json['minScale']))
print('MaxScale = {}'.format(service_layer_json['maxScale']))
# MinScale = 1155582
# MaxScale = 0
#Update scale range
service_layer_json['minScale'] = 15000
service_layer_json['maxScale'] = 150
#Check new scale range
print('MinScale = {}'.format(service_layer_json['minScale']))
print('MaxScale = {}'.format(service_layer_json['maxScale']))
# MinScale = 15000
# MaxScale = 150
# Apply edits to the service
# Make sure that url is not in the properties
if 'editingInfo' in service_layer_json:
del service_layer_json['editingInfo']
result = feature_layer.manager.update_definition(service_layer_json)
result
# {'success': True}
# Testing that changes have been applied
feature_layer_item = gis.content.get('96d90824c0b94025abefeb7fe0ef60a0')
# Get service content info
request = requests.get(feature_layer.url + '?f=pjson&token={}'.format(gis._con.token))
service_layer_json = request.json()
#Check current scale range
print('MinScale = {}'.format(service_layer_json['minScale']))
print('MaxScale = {}'.format(service_layer_json['maxScale']))
# MinScale = 15000
# MaxScale = 150
Thank you very much for your reply. When running .update_definition(), I am encountering the following error message: Field 'currentVersion' cannot be updated. Note sure whether others encounter this issue as well, it works for me when adjusting the code like this:
from arcgis.gis import GIS
import getpass
password = getpass.getpass("Enter password: ")
gis = GIS('<PortalUrl>', '<username>', password)
portalItemId = '<PortalItemId>'
from arcgis.features import FeatureLayer
feature_layer_item = gis.content.get(portalItemId)
feature_layer = feature_layer_item.layers[0]
feature_layer
# only name fields which should be updated
service_layer_json = {
"maxScale": 150,
"minScale": 15000
}
result = feature_layer.manager.update_definition(service_layer_json)
result
# {'success': True}
Basically, I am not using the service_layer_json retrieved from the service itself, but created an own service_layer_json object which only has the fields which should be updated.
Yeah, that would do the trick.
In my case, i just copied code from another workflow where I had to check what were the values before deciding if they needed to updated or not. There are some values that you have to make sure doesn't exists on the json that you update such as "editingInfo" or "sourceSchemaChangesAllowed" or "hasViews" and on the flow where we first take the json fron the layer and modify it, those need to be removed. I'm not aware of a list which defines values that cannot be send back to the service so it's trial and error. Generally those values are "system-maintained-fields". Anyhow, I think that the basic flow where you just define the values that requires updating is super solid and helps in sooo many cases. I use this (on the feature layer level) to make sure that descriptions and copyright information gets correctly updated and stays in sync with the item level values for example.