Select to view content in your preferred language

create_view is changing service definition on parent item

154
4
Jump to solution
Tuesday
JamesTurner2
Frequent Contributor

I am trying to create a hosted feature layer view that contains 2 out of 3 layers in a service. When I run create_view, my view is created correctly with 2 layers, but for some reason it is effecting the source item as well. When I go to the source item page, I only see two layers listed, however, all 3 layers are still listed if I look at the service URL. Not sure what's going on here, if I create a second view with different layers, the source item returns to normal. 

## get feature service
source_item = portal.content.get("9ab20e7f7f7d4a89b0d6c053a03e6305")

# Get a FeatureLayerCollection from the item
source_flc = FeatureLayerCollection.fromitem(source_item)

# Create dict of layers in service name:url
layer_lookup = {
    lyr.properties.name: lyr
    for lyr in source_flc.layers
}

# Configuration for each layer in the new view
layer_configs = {
    "Tracks": {
        "query": "inspection_year = '2025'",
        "hidden_fields": ["agency", "updates_req"]
    }
    ,
    "Clubs": {
        "query": "insp_years = 'Even'",
        "hidden_fields": ["closed_miles"]
    }
}

# Use dict keys from layer_config to get service URL to use in view_layers, this defines which layers are included
view_layers = [
    layer_lookup[name] for name in layer_configs.keys()
]

# Create the view layer
vw_name = "2025_Inspection_Tracks"
view_capabilities = "Query,Create,Update,Delete,Editing,Sync" 
view_item = source_flc.manager.create_view(name=vw_name
                                    , view_layers=view_layers
                                    )

 

0 Kudos
1 Solution

Accepted Solutions
Clubdebambos
MVP Regular Contributor

Hi @JamesTurner2,

What version of the API are you using? I had this issue before but I haven't checked if it is still happening in the latest version (2.4.3 at time of writing).

The JSON data behind the service is getting manipulated. If you look at the original service in AGO Assistant or print the item object get_data() dictionary to screen, you will see only two layer defined.

Similar happens with the insert_layer(). I have a video here detailing how to fix that, and a it would be similar for here. See code below.

from arcgis.gis import GIS

## access AGOL
agol = GIS("home")

## get the item object
item = agol.content.get("FS_ITEM_ID")

## item data layer dictionary template
lyr_dict = {
    "id" : None,
    "blendMode" : "normal",
    "layerDefinition" : {},
    "disablePopup" : False,
    "popupInfo" : {
        "popupElements" : [
            {
                "type" : "fields",
                "fieldInfos" : None
            }
        ]
    }
}

## get the FeatureLayer object - USE THE INDEX FOR THE MISSING LAYER
fl = flc.layers[0]

## update the id key
lyr_dict["id"] = fl.properties.id

## update the layerDefinition key (symbology))
lyr_dict["layerDefinition"]["drawingInfo"] = fl.properties.drawingInfo

## get the field info for the popup
field_infos = []
for field in fl.properties.fields:
    field = dict(field)
    field_dict = {
        "fieldName" : field["name"],
        "isEditable" : field["editable"],
        "label" : field["alias"],
        "visible" : True
    }
    field_infos.append(field_dict)

## apply the field infos
lyr_dict["popupInfo"]["popupElements"][0]["fieldInfos"] = field_infos

## get the item JSON data
item_data = item.get_data()

## update layers
item_data["layers"] = item_data["layers"] + [lyr_dict]

## update the Item
update_dict = {
    "text" : item_data
}

item.update(
    item_properties = update_dict
)

 

~ learn.finaldraftmapping.com

View solution in original post

4 Replies
Clubdebambos
MVP Regular Contributor

Hi @JamesTurner2,

What version of the API are you using? I had this issue before but I haven't checked if it is still happening in the latest version (2.4.3 at time of writing).

The JSON data behind the service is getting manipulated. If you look at the original service in AGO Assistant or print the item object get_data() dictionary to screen, you will see only two layer defined.

Similar happens with the insert_layer(). I have a video here detailing how to fix that, and a it would be similar for here. See code below.

from arcgis.gis import GIS

## access AGOL
agol = GIS("home")

## get the item object
item = agol.content.get("FS_ITEM_ID")

## item data layer dictionary template
lyr_dict = {
    "id" : None,
    "blendMode" : "normal",
    "layerDefinition" : {},
    "disablePopup" : False,
    "popupInfo" : {
        "popupElements" : [
            {
                "type" : "fields",
                "fieldInfos" : None
            }
        ]
    }
}

## get the FeatureLayer object - USE THE INDEX FOR THE MISSING LAYER
fl = flc.layers[0]

## update the id key
lyr_dict["id"] = fl.properties.id

## update the layerDefinition key (symbology))
lyr_dict["layerDefinition"]["drawingInfo"] = fl.properties.drawingInfo

## get the field info for the popup
field_infos = []
for field in fl.properties.fields:
    field = dict(field)
    field_dict = {
        "fieldName" : field["name"],
        "isEditable" : field["editable"],
        "label" : field["alias"],
        "visible" : True
    }
    field_infos.append(field_dict)

## apply the field infos
lyr_dict["popupInfo"]["popupElements"][0]["fieldInfos"] = field_infos

## get the item JSON data
item_data = item.get_data()

## update layers
item_data["layers"] = item_data["layers"] + [lyr_dict]

## update the Item
update_dict = {
    "text" : item_data
}

item.update(
    item_properties = update_dict
)

 

~ learn.finaldraftmapping.com
JamesTurner2
Frequent Contributor

I am using version 2.4.1.1 on Enterprise 11.5. Your code helped me get to a solution, I had recognized that the issue was in the JSON but couldn't figure out how to fix it! Thanks!

JamesTurner2
Frequent Contributor

I upgraded my API to 2.4.3 and it appears to have the same issue. With your approach, redefining the JSON for the missing layers, customized pop ups are wiped out (as expected given the code). Given my workflow of creating views instead of inserting layers, I can just copy all the JSON before running create_view and then if any layers are missing, replace all the JSON with the original. 

# Get feature service
source_item = portal.content.get("42...3ec")

# Get a FeatureLayerCollection from the item
source_flc = FeatureLayerCollection.fromitem(source_item)

# Get source_item JSON before creating the view
item_data_backup = source_item.get_data()

backup_layers = {
    lyr["id"]: lyr
    for lyr in item_data_backup.get("layers", [])
}

backup_ids = set(backup_layers.keys())

# Create the view layer
vw_name = "tracks_2"
view_item = source_flc.manager.create_view(name=vw_name)

# Get the source_item JSON after creating the view
item_data = source_item.get_data()

current_ids = {
    lyr["id"]
    for lyr in item_data.get("layers", [])
}

# Find missing layer IDs
missing_ids = backup_ids - current_ids

if missing_ids:

    print(
        f"Detected {len(missing_ids)} missing layer(s) in source item JSON. "
        "Restoring from backup."
    )

    print(f"Missing layer IDs: {sorted(missing_ids)}")

    # Restore the entire layers array from backup
    # in the same order as the service definition
    item_data["layers"] = [
        backup_layers[fl.properties.id]
        for fl in source_flc.layers
        if fl.properties.id in backup_layers
    ]

    source_item.update(
        item_properties={"text": item_data}
    )

    print("Finished restoring parent layer JSON from backup")

else:
    print("No missing layers")
0 Kudos
Clubdebambos
MVP Regular Contributor

Yes, exactly. Nicely done.

~ learn.finaldraftmapping.com
0 Kudos