Previously, I wrote an document on how to overwrite an ArcGIS Online feature service by referencing a feature class and using a truncate/append method. I received a lot of feedback from this document, with some users encountering limitations such as attachments not being supported, and updating services containing multiple layers. This solution is aimed to address these limitations. Below is a script to overwrite an ArcGIS Online feature service by referencing an ArcGIS Pro project, and a video on how to use the script. Please comment below if there are any issues or questions.
import arcpy, os, time, requests, json
from arcgis.gis import GIS
from arcgis.features import FeatureLayerCollection
# Variables
prjPath = r"C:\Projects\GeoNET\GeoNET.aprx" # Path to Pro Project
map = 'State Parks' # Name of map in Pro Project
serviceDefID = '3fa1620c47dc490db43b9370e8cf5df8' # Item ID of Service Definition
featureServiceID = 'fb42ef7b43154f95b8b6ad7357b7f663' # Item ID of Feature Service
portal = "https://www.arcgis.com" # AGOL
user = "jskinner_rats" # AGOL username
password = "********" # AGOL password
preserveEditorTracking = True # True/False to preserve editor tracking from feature class
unregisterReplicas = True # True/False to unregister existing replicas
# Set Environment Variables
arcpy.env.overwriteOutput = 1
# Disable warnings
requests.packages.urllib3.disable_warnings()
# Start Timer
startTime = time.time()
print(f"Connecting to AGOL")
gis = GIS(portal, user, password)
arcpy.SignInToPortal(portal, user, password)
# Local paths to create temporary content
sddraft = os.path.join(arcpy.env.scratchFolder, "WebUpdate.sddraft")
sd = os.path.join(arcpy.env.scratchFolder, "WebUpdate.sd")
sdItem = gis.content.get(serviceDefID)
# Create a new SDDraft and stage to SD
print("Creating SD file")
arcpy.env.overwriteOutput = True
prj = arcpy.mp.ArcGISProject(prjPath)
mp = prj.listMaps(map)[0]
serviceDefName = sdItem.title
arcpy.mp.CreateWebLayerSDDraft(mp, sddraft, serviceDefName, 'MY_HOSTED_SERVICES',
'FEATURE_ACCESS', '', True, True)
arcpy.StageService_server(sddraft, sd)
# Reference existing feature service to get properties
fsItem = gis.content.get(featureServiceID)
flyrCollection = FeatureLayerCollection.fromitem(fsItem)
properties = fsItem.get_data()
capabilities = flyrCollection.manager.properties
# Get thumbnail and metadata
thumbnail_file = fsItem.download_thumbnail(arcpy.env.scratchFolder)
metadata_file = fsItem.download_metadata(arcpy.env.scratchFolder)
# Unregister existing replicas
enableSync = False
if unregisterReplicas:
if flyrCollection.properties.syncEnabled:
enableSync = True
print("Unregister existing replicas")
for replica in flyrCollection.replicas.get_list():
replicaID = replica['replicaID']
flyrCollection.replicas.unregister(replicaID)
# Overwrite feature service
sdItem.update(data=sd)
print("Overwriting existing feature service")
if preserveEditorTracking:
pub_params = {"editorTrackingInfo" : {"preserveEditUsersAndTimestamps":'true'}}
fs = sdItem.publish(overwrite=True, publish_parameters=pub_params)
else:
fs = sdItem.publish(overwrite=True)
# Update service with previous properties
print("Updating service properties")
item_properties = {"text": json.dumps(properties)}
fs.update(item_properties=item_properties)
flyrCollection.manager.update_definition(capabilities)
# Update thumbnail and metadata
print("Updating thumbnail and metadata")
fs.update(thumbnail=thumbnail_file, metadata=metadata_file)
print("Clearing scratch directory")
arcpy.env.workspace = arcpy.env.scratchFolder
for file in arcpy.ListFiles():
if file.split(".")[-1] in ('sd', 'sddraft', 'png', 'xml'):
arcpy.Delete_management(file)
endTime = time.time()
elapsedTime = round((endTime - startTime) / 60, 2)
print(f"Script completed in {elapsedTime} minutes")
Updates
Update 2/2/24: Added the option to unregister existing replicas
Update 12/2/24: Sync is re-enabled if it was previously enabled