Using Python to Update Definition Query

3265
6
Jump to solution
03-22-2021 02:36 PM
KathrynWesson
New Contributor III

Hi! Need some help fixing a code I found online and am trying to customize to my needs. I have a series of 90 map documents, where each one is a different school district and shows the railroad crossings within its boundaries. What I would like the code to do is iterate through each map document, select by location all crossings that intersect the school district within 150 feet, create a list of the ObjectIDs from those selected points, then throw that list of values into the layer's definition query. The list of crossings should therefore be unique to each map document. Here is what I have so far (not set up for iteration yet):

 

 

mxd = arcpy.mapping.MapDocument("CURRENT")

df = arcpy.mapping.ListDataFrames(mxd, '')[0]

for lyr in arcpy.mapping.ListLayers(mxd):
    if lyr.name == "Crossings":
        Point = lyr
    if lyr.name == "Current School District Boundaries":
        Polygon = lyr

arcpy.SelectLayerByLocation_management(Point, "WITHIN_A_DISTANCE", Polygon, "150 Feet", "NEW_SELECTION")

pointList = []

for row in arcpy.SearchCursor(Point):
    strrow = str(row.OBJECTID)
    pointList.append(strrow)

txt_row = ','.join(pointList)
row_list = '(' + txt_row + ')'

for lyr in arcpy.mapping.ListLayers(mxd):
    if lyr.name == "Point":
        lyr.definitionQuery = ' "OBJECTID IN" + row_list '

arcpy.SelectLayerByAttribute_management(Point, "CLEAR_SELECTION")
arcpy.SelectLayerByAttribute_management(Polygon, "CLEAR_SELECTION")

arcpy.RefreshActiveView()
arcpy.RefreshTOC()

mxd.save()

 

 

 I can see the code working when I run it, and it doesn't kick out any errors, but when I check the definition query, it hasn't updated. What am I doing wrong? Thanks in advance!

0 Kudos
1 Solution

Accepted Solutions
RandyBurton
MVP Alum

Both Joe and Dan have good suggestions.  You are also quoting "Point" in the block where you are setting the definition query.  Since you were using the old SearchCursor, I will assume you are using Desktop.  Try:

 

mxd = arcpy.mapping.MapDocument("CURRENT")

Point = "MyFeature" # your code sets this

# picking up with:

pointList = []

with arcpy.da.SearchCursor(Point,['OBJECTID']) as cursor:
    for row in cursor:
        pointList.append(str(row[0])) # row[0] is ObjectID

defQuery = "OBJECTID IN ({})".format(",".join(pointList))
# print defQuery  # to verify, if needed

for lyr in arcpy.mapping.ListLayers(mxd):
    if lyr.name == Point:   # remove quotes around Point
        lyr.definitionQuery = defQuery

# continue   

 

 

 

View solution in original post

6 Replies
JoeBorgione
MVP Emeritus
for row in arcpy.SearchCursor(Point):
    strrow = str(row.OBJECTID)
    pointList.append(strrow)

This part catches my attention: is there some specific reason you are using the old style SearchCursor() rather than the new (and suggested) arcpy.da.SearchCursor()?  The syntax that I am familiar with requires some sort of field name reference:

fields = ['OBJECTID']
for row in arcpy.da.SearchCursor(Point, Fields):
  blah blah blah....

# or
with arcpy.da.SearchCursor(Point, '*'): as cursor:
    for row in cursor:
        blah blah blah

You can throw in a print() statement to see what the value is of strrow and or what PointList looks like.

Is this being run as a stand alone script?  I'm not sure how l layers are actually used in  the .mapping module, as most of my experience is limited to working on features themselves and in that case I have to use Make feature layer first and apply the selection to that.

That should just about do it....
KathrynWesson
New Contributor III

Thank you for your help! @RandyBurton had a line in his solution code that worked for me. I was using this code in the Python window via ArcMap 10.8.1 and wanted to avoid creating a new layer (in memory or otherwise) in the TOC. I'm also not very proficient at Python so I apologize if my question or replies don't make sense. Thanks again!

0 Kudos
DanPatterson
MVP Esteemed Contributor

I think you need to "str" OBJECTID

pointList = [1, 2, 3, 4, 5]

strList = ", ".join([str(i) for i in pointList])

row_list = '(' + strList + ')'

OBJECTID = 3

OBJECTID in row_list

Traceback (most recent call last):
  File "<ipython-input-8-20e4d7a1270a>", line 1, in <module>
    OBJECTID in row_list
TypeError: 'in <string>' requires string as left operand, not int


str(OBJECTID) in row_list  # ---- str the id
True

... sort of retired...
KathrynWesson
New Contributor III

Wasn't it already converted to string on line 17, though? I don't "speak" Python at all, so I'm sorry if I don't grasp the concept. Anyway, there were a couple of commands in @RandyBurton 's answer that I did not have in my original code, but once I included those, it worked. Thanks for your time and effort helping me out!

0 Kudos
RandyBurton
MVP Alum

Both Joe and Dan have good suggestions.  You are also quoting "Point" in the block where you are setting the definition query.  Since you were using the old SearchCursor, I will assume you are using Desktop.  Try:

 

mxd = arcpy.mapping.MapDocument("CURRENT")

Point = "MyFeature" # your code sets this

# picking up with:

pointList = []

with arcpy.da.SearchCursor(Point,['OBJECTID']) as cursor:
    for row in cursor:
        pointList.append(str(row[0])) # row[0] is ObjectID

defQuery = "OBJECTID IN ({})".format(",".join(pointList))
# print defQuery  # to verify, if needed

for lyr in arcpy.mapping.ListLayers(mxd):
    if lyr.name == Point:   # remove quotes around Point
        lyr.definitionQuery = defQuery

# continue   

 

 

 

KathrynWesson
New Contributor III

Yes, that worked! Thank you so much! Haven't set it up to iterate yet, but for anyone else who comes across this, here is my updated code that worked for my situation:

mxd = arcpy.mapping.MapDocument("CURRENT")

df = arcpy.mapping.ListDataFrames(mxd, '')[0]

for lyr in arcpy.mapping.ListLayers(mxd):
    if lyr.name == "Crossings":
        Point = lyr
    if lyr.name == "Current School District Boundaries":
        Polygon = lyr

arcpy.SelectLayerByLocation_management(Point, "WITHIN_A_DISTANCE", Polygon, "150 Feet", "NEW_SELECTION")

pointList = []

with arcpy.da.SearchCursor(Point,['OBJECTID']) as cursor:
    for row in cursor:
        pointList.append(str(row[0]))

defQuery = "Purpose = 1 AND OBJECTID IN ({})".format(",".join(pointList))

for lyr in arcpy.mapping.ListLayers(mxd):
    if lyr.name == "Crossings":
        lyr.definitionQuery = defQuery

arcpy.SelectLayerByAttribute_management(Point, "CLEAR_SELECTION")
arcpy.SelectLayerByAttribute_management(Polygon, "CLEAR_SELECTION")

arcpy.RefreshActiveView()
arcpy.RefreshTOC()

mxd.save()

 

0 Kudos