Been doing some searching here and with the online help; I don't know if this is possible or not:
Create a feature layer and apply a definition query to that feature layer. Then use the feature layer to clip another feature class. I can always make a selection to the feature layer and use the it to clip the feature class, but I'm just wondering....
Solved! Go to Solution.
@Luke_Pinner Perfect. Why didn’t I think of that?!
Hello, This took a lot longer than I think it should have to code up and test, so we wanted to share. We find replace string/s. This runs in or out of Pro.
#project = arcpy.GetParameterAsText(0)
#old_asset_name = arcpy.GetParameterAsText(1)
#new_asset_name = arcpy.GetParameterAsText(2)
old_asset_name = "Template"
new_asset_name = "AssetName"
project = (r'Your.aprx')
aprx = arcpy.mp.ArcGISProject(project)
m = aprx.listMaps()[0]
# List of Layers in TOC
for lyr in m.listLayers():
arcpy.AddMessage(str(lyr))
arcpy.AddMessage("\n")
## Layer Validation
if lyr.supports("DEFINITIONQUERY"):
# Lists Definition Queries
query = lyr.listDefinitionQueries()
arcpy.AddMessage("Old DQ " + str(query))
## List Dictionary
for dic in query:
# Open dictionary item
for key, value in dic.items():
if key == 'sql':
## print("")
## print(value)
## Find Replace
replace = value.replace(old_asset_name, new_asset_name)
## print("")
## print("SQL " + str(replace))
## Update DIctionary
dic[key] = replace
## print("")
## print("New Query " + str(query))
## update Definition Queries
lyr.updateDefinitionQueries(query)
new_query = lyr.listDefinitionQueries()
arcpy.AddMessage("New DQ " + str(new_query))
arcpy.AddMessage("")
aprx.saveACopy(project)
Yes this is possible by accessing the CIM definition for the feature layer. You can read more about that here. https://pro.arcgis.com/en/pro-app/latest/arcpy/mapping/python-cim-access.htm
As for an example, this is roughly what you need to update a layer's definition query, then run your clip afterwards.
def set_definition_query(map_name, layer_name, definition_query):
aprx = arcpy.mp.ArcGISProject("CURRENT")
for map in aprx.listMaps(map_name):
for layer in map.listLayers():
if layer.name == layer_name:
cim = layer.getDefinition('V2')
# You may not need to update definitionFilterChoices
cim.featureTable.definitionFilterChoices[0].definitionExpression = definition_query
cim.featureTable.definitionExpression = definition_query
layer.setDefinition(cim)
# Sample data
map_name = 'Map'
lyr_name = 'MyLayer'
oid = 200
definition = f"OBJECTID = '{oid}'"
set_definition_query(map_name, lyr_name, definition)
Thanks @nzjs . I should have clarified that I don't have an aprx; I'm just going straight to the data source. I'll see if I can adapt your code to my specific application.
I see - in your case you probably do want to use Select by Attribute arcpy tool as mentioned in your post. I'm fairly certain that using and modifying the CIM is more a case of needing to adjust symbology, definition query, popups, etc within an ArcGIS Pro project/maps.
Adjusted this slightly but now I can edit a single DQ through arcpy... before everytime I altered the query from arcpy it created a whole new DQ, so I was ending up with a whole list of DQ's.
You saved me a headache, cheers! 🍻
Layer's have a definitionQuery property, just set or update it after creating the layer: Layer—ArcGIS Pro | Documentation
>>> import arcpy
>>>
>>> fc = # path to feature class
>>> fl = arcpy.management.MakeFeatureLayer(fc)[0]
>>> fl
<arcpy._mp.Layer object at 0x000001E44F9BB388>
>>> fl.definitionQuery
''
>>> arcpy.management.GetCount(fl)
<Result '5'>
>>> fl.definitionQuery = "OBJECTID < 3"
>>> arcpy.management.GetCount(fl)
<Result '2'>
>>>
Include a where clause in arcpy.management.MakeFeatureLayer (see the "Expression" parameter)
@Luke_Pinner Perfect. Why didn’t I think of that?!
Hello, This took a lot longer than I think it should have to code up and test, so we wanted to share. We find replace string/s. This runs in or out of Pro.
#project = arcpy.GetParameterAsText(0)
#old_asset_name = arcpy.GetParameterAsText(1)
#new_asset_name = arcpy.GetParameterAsText(2)
old_asset_name = "Template"
new_asset_name = "AssetName"
project = (r'Your.aprx')
aprx = arcpy.mp.ArcGISProject(project)
m = aprx.listMaps()[0]
# List of Layers in TOC
for lyr in m.listLayers():
arcpy.AddMessage(str(lyr))
arcpy.AddMessage("\n")
## Layer Validation
if lyr.supports("DEFINITIONQUERY"):
# Lists Definition Queries
query = lyr.listDefinitionQueries()
arcpy.AddMessage("Old DQ " + str(query))
## List Dictionary
for dic in query:
# Open dictionary item
for key, value in dic.items():
if key == 'sql':
## print("")
## print(value)
## Find Replace
replace = value.replace(old_asset_name, new_asset_name)
## print("")
## print("SQL " + str(replace))
## Update DIctionary
dic[key] = replace
## print("")
## print("New Query " + str(query))
## update Definition Queries
lyr.updateDefinitionQueries(query)
new_query = lyr.listDefinitionQueries()
arcpy.AddMessage("New DQ " + str(new_query))
arcpy.AddMessage("")
aprx.saveACopy(project)