Create a Definition Query in Standalone Arcpy/Python Script

1945
7
Jump to solution
08-18-2021 03:11 PM
JoeBorgione
MVP Esteemed Contributor

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....

That should just about do it....
0 Kudos
2 Solutions

Accepted Solutions
JoeBorgione
MVP Esteemed Contributor

@Luke_Pinner  Perfect. Why didn’t I think of that?!

That should just about do it....

View solution in original post

0 Kudos
dbKlingdom
New Contributor

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)

View solution in original post

0 Kudos
7 Replies
nzjs
by
New Contributor III

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)

 

JoeBorgione
MVP Esteemed Contributor

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.

That should just about do it....
0 Kudos
nzjs
by
New Contributor III

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.

0 Kudos
JoshuaBixby
MVP Esteemed Contributor

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'>
>>> 

 

 

Luke_Pinner
MVP Regular Contributor

Include a where clause in arcpy.management.MakeFeatureLayer (see the "Expression" parameter)

JoeBorgione
MVP Esteemed Contributor

@Luke_Pinner  Perfect. Why didn’t I think of that?!

That should just about do it....
0 Kudos
dbKlingdom
New Contributor

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)

0 Kudos