Error: Object has no attribute 'id'

Good morning Team,

I am running an update query on a table and i am getting an error. I see where the error is happening but not sure on how to correct.

Query to populate the tabel:

SELECT id, case_type, chute, chute_area, target, ordered, state
FROM chutes

Query to update the tabel:

UPDATE `Clemens`.`chutes` SET `case_type` =  :case_Type , `target` =  :targetQTY , `state` =  :stateAvail  WHERE (`id` =  :iD );

Configure on Action Performed

def runAction(self, event):
	import time
	    	
	case_type = self.getSibling("Table").props.selection.data[0].case_type
	target = self.getSibling("Table").props.selection.data[0].target
	state = self.getSibling("Table").props.selection.data[0].state
	id = self.getSibling("Table").props.selection.data[0].id
	category = "HMI"
	source = "ASCADA Client"
	usr = self.session.props.auth.user.id
	message = str(usr) + " Inserted  " + str(case_type), str(target) + " in WCS "
	data9 = usr	
				# Insert new SKU
	system.db.runNamedQuery("Tables/Chutes_Updates",{
			"caseType": case_type,
	    	"targetQTY": target,
	    	"stateAvail": state,
	    	"iD": id
	    	})
	    
	time.sleep(2)
	    	
	   	# Refresh table data
	self.getSibling("Table").refreshBinding()
	    					
		#Update Syslog		
	system.db.runNamedQuery("Tables/syslog_update",{
			"category": category,
	    	"source": source,
	    	"message": message,
	    	"data9": data9
	    	})
	time.sleep(2)				
	    
	self.getSibling("Table").props.selection.data[0].case_type= " "
	self.getSibling("Table").props.selection.data[0].target= " "
	self.getSibling("Table").props.selection.data[0].state= " "
	self.getSibling("Table").props.selection.data[0].id= " "

does selection.data[0] actually have an id attribute in it in the designer for example? or you could system.perspective.log it.

You may need to include it as a column but then hide the column from the table in the columns property in the property tree

There is an id, that does not change, but is used to udpate that row's information.

I had the column in the table, hidden.

Here is is unhidden.

so if you system.perspective.print(self.getSibling("Table").props.selection.data[0])
what is the browser consoles output?

Traceback (most recent call last):
File "", line 1, in
AttributeError: 'com.inductiveautomation.ignition.designer.gui.tool' object has no attribute 'perspecitve'

Also, as a note the ID is configured to the PLC array index.

image
that error does not make sense to me if you are using this in an event handler...

You misspelled

as did I originally

I changed the row to show as visible and it looks like it is running but it did not update the tabel.

Now when I execute the command it does not update.

I have changed the udpate query to use the values and it only works with the 'state' is in ' ' like 'Available'.

UPDATE `Clemens`.`chutes` 
SET `case_type` =  :case_Type , `target` =  :targetQTY , `state` =  :stateAvail
WHERE (`id` =  :iD );
UPDATE `Clemens`.`chutes` 
SET `case_type` =  102 , `target` =  222 , `state` =  'Available'
WHERE (`id` =  2 );

How do I fix that in my change script so it puts the 'state' in quotes?

Anyone have an idea?

I see sleep(2) twice in that script, so I'll suggest that the whole thing needs to be reworked.

Can you explain what you need to do ?

You shouldn't need them, passing parameters of the correct type to the named query will do that for you.

What flavor of DB are you using? You should not have Single Quotes around your column names.

I would expect your query to look like this:

UPDATE Clemens.chutes
SET case_type = :case_Type, target = :targetQTY, state = :stateAvail
WHERE id = :iD

Notice the lack of back ticks and quotes.

Looking at your script, I see you are using time.sleep. This is a big no, no. Don't do it, you're tanking your performance as well as potentially creating other issues. You just do not need a forced delay here as system.db.runNamedQuery() is a blocking function so the rest of the code will not execute until it has returned anyway.

Also, you are using id as a variable name, it is a builtin and should not be used like this.

And might I suggest that rather than using a space " " for "Empty", use a value that is appropriate for the column type.

I would expect your script to look something like this:

case_type = self.getSibling("Table").props.selection.data[0].case_type
target = self.getSibling("Table").props.selection.data[0].target
state = self.getSibling("Table").props.selection.data[0].state
rowId = self.getSibling("Table").props.selection.data[0].id

args = {
        "caseType":case_type,
        "targetQTY":target,
        "stateAvail":state,
        "iD":rowId
        }
system.db.runNamedQuery("Tables/Chutes_Updates", args)

self.getSibling("Table").refreshBinding()

userID = self.session.props.auth.user.id

system.db.runNamedQuery("Tables/syslog_update",{
        "category":"HMI",
        "source":"ASCADA Client",
        "message":"{} Inserted {}, {} in WCS".format(userId, case_type, target)
        "data9":userID
        })
self.getSibling("Table").props.selection.data[0].case_type = 0
self.getSibling("Table").props.selection.data[0].target = 0
self.getSibling("Table").props.selection.data[0].state = ""
self.getSibling("Table").props.selection.data[0].id = None

Ideally the majority of this script would probably be a library function that was called from a message handler on the table, rather than run in the event on the button.

3 Likes

how would teh message handler look?

I imagine that it would look something like this:

def onMessageReceived(self, payload):
	lib.updateChutes(self.props.selection.data[0])
	self.refreshBinding()

I just now noticed the backtics myself. you can use "columnName" for most SQL as well as [columnName]

lrose, thanks so much for helping.

I have everything set but one field is not updating, the case_type.

Here is the code to run the update and they query in perspective.

I believe it is a formatting issue. When I run the query it puts a null in this column.

UPDATE Clemens.chutes
SET case_type = :case_Type, target = :targetQTY, state = :stateAvail
WHERE id = :iD
def runAction(self, event):
	    	
	case_type = self.getSibling("Case Type").props.value
	target = self.getSibling("Quantity").props.value
	state = self.getSibling("Status").props.value
	rowid = self.getSibling("Table").props.selection.data[0].id
	category = "HMI"
	source = "ASCADA Client"
	usr = self.session.props.auth.user.id
	message = str(usr) + " Inserted  " + str(case_type), str(target) + " in WCS "
	data9 = usr	
				# Insert new SKU
	system.db.runNamedQuery("Tables/Chutes_Updates",{
			"caseType": case_type,
	    	"targetQTY": target,
	    	"stateAvail": state,
	    	"iD": rowid
	    	})
	    
	    	
	   	# Refresh table data
	self.getSibling("Table").refreshBinding("props.data")
	    					
		#Update Syslog		
	system.db.runNamedQuery("Tables/syslog_update",{
			"category": category,
	    	"source": source,
	    	"message": message,
	    	"data9": data9
	    	})
	   
	self.getSibling("Table").props.selection.data[0].case_type = ""
	self.getSibling("Table").props.selection.data[0].target = ""
	self.getSibling("Table").props.selection.data[0].state = ""
	self.getSibling("Table").props.selection.data[0].id = None    

In addtion, i have my drop down options reading from a tabel to populate the qeury.

The key in your params dictionary must match exactly what you have set up in the Named Query.

so "caseType" should be "case_Type". That was how you had it in your original script, and I didn't check it against the parameter names.

1 Like

I'd change the parameter in the named query to caseType, to be consistent with the other parameters.

1 Like