Let's say I need to add a new statement to an existing Def query to all layers in a group which would like like something like this:
aprx = arcpy.mp.ArcGISProject("CURRENT")
m = aprx.listMaps("Map")[0]
for lyr in m.listLayers():
if lyr.supports ("longname"):
parent = lyr.longName.split('\\')
if parent [0] == "Group":
print (lyr.longName)
if lyr.supports("DEFINITIONQUERY"):
oldDefQuery = lyr.definitionQuery
lyr.definitionQuery = None
newDefQuery = oldDefQuery + " CODE = 0"
lyr.definitionQuery = newDefQuery
What happens after running the script is that the old definition query becomes inactive and the newly created query is added and becomes active. However they both remain the same query name and seem to clash with each other so that no feature pass through the query (don't mind the fieldnames):
There seem to be no detailed explanation on the definitionQuery property at Layer—ArcPy | ArcGIS Desktop
So the questions are:
Thanks heaps!
Did you ever manage to solve this?
Since I am not sure of the OP's code indentations, I will focus on once you have a reference to a layer:
sql = # Additional WHERE clause to append to existing
lyr_cim = lyr.getDefinition('V2')
cim_ft = lyr_cim.featureTable
defExpName = cim_ft.definitionExpressionName
defExpIdx = next(
i for
i,n in
enumerate(cim_ft.definitionFilterChoices)
if n.name == defExpName
)
cim_ft.definitionExpression += sql
cim_ft.definitionFilterChoices[defExpIdx] = cim_ft.definitionExpression
lyr.setDefinition(lyr_cim)
No, haven't solved this entirely. The easiest workaround was to go back to ArcMap.
Since Esri exposed the CIM model to ArcPy starting with Pro 2.4 (or was it 2.3), it opened the doors to doing a lot more within Pro that wasn't available strictly through ArcPy in the past with Pro.
This seemed to work. It changed the def query without the duplication. Note that you have to change two CIM properties to get this to change without duplication AND to make the new query the 'active' query.
# sorry for bad indents; I don't know how to format this here
# batch change (all maps in project) definition query for a specified layer
# optional param - specify which map you want to target, default is that it does all of them
def batch_change_definition_query(layer_name, definition_query, my_map = None):
aprx = arcpy.mp.ArcGISProject("CURRENT")
for map in aprx.listMaps(my_map):
for layer in map.listLayers():
if layer.name == layer_name:
cim_layer = layer.getDefinition('V2')
cim_layer.featureTable.definitionFilterChoices[0].definitionExpression = definition_query
cim_layer.featureTable.definitionExpression = definition_query
layer.setDefinition(cim_layer)
I was able to get this method to work as well. For context: I am running script tools that allow users to set and clear definition queries for multiple layers. When setting, they select a value from a drop down list and run the script which creates and applies the query with their selected value to all the relevant layers. When clearing, they simply run the script tool and all definition queries are cleared from the relevant layers.
Here is an example of the syntax I used for clearing queries. I am into an issue where it gave an error if the layer didn't already have a DQ on it, so it couldn't overwrite it. So I check for existing DQs first, if there is one, I overwrite it, if there isn't one, I create and apply one.
aprx = arcpy.mp.ArcGISProject("CURRENT")
m = aprx.activeMap
lyrs = m.listLayers()
for lyr in lyrs:
if lyr.name in ('TEST_PT', 'TEST_LINE', 'TEST_POLY'):
cim_layer = lyr.getDefinition('V2')
if cim_layer.featureTable.definitionFilterChoices:
cim_layer.featureTable.definitionFilterChoices[0].definitionExpression = None
cim_layer.featureTable.definitionExpression = None
else:
cim_layer.featureTable.definitionExpression = None
lyr.setDefinition(cim_layer)
Doing it this way allowed me to create, apply, and clear definition queries without creating a massive list of deactivated queries for each layer. Hope this helps others.
For others looking for help in this space.
I've just tested the below line in a python script that looks at a set map (Data Editing) in the Current project, and had the last 2 lines repeated for all the different layer names that I wanted it to update. It successfully deleted the definition query from each layer.
aprx = arcpy.mp.ArcGISProject("CURRENT")
m = aprx.listMaps("Data Editing")[0]
for lyr in m.listLayers("Layer 1"): ###Repeat these 2 lines for each layer
lyr.definitionQuery = None
for lyr in m.listLayers("Layer 2"):
lyr.definitionQuery = None
I plan to write a simple script that can be used on any project and map which will just go through all layers in the current map and wipe and definition queries. Variations of this could include a 3rd line for each layer that adds a replacement query in the originals place.
Sorry, lyr.definitionQuery = None does not work. It still is keeping all query clauses. Frustrating.