QSqlTableModel.setData error but lastError() always empty - python

you're help is needed:
the mystery is located in Method setupNumRibs.
In my test setup the table contains only one row.
res = self.setData(self.index(0, 1), numRows )
Executes and does the table update as expected.
res = self.setData(self.index(1, 1), numRows )
Must fail, as the row to be updated does not exist.
res is FALS as expected, BUT on the cmd line I get:
model ErrT : 0
model Err text : ||
db ErrT : 0
db Err text : ||
Somwhow the
modelError = self.lastError()
Fails, I don't get the correct info back, but I don't see WHY :-(
The full code:
from Singleton.Singleton import Singleton
class ProcessorModel(QSqlTableModel, metaclass=Singleton):
def __init__(self, parent=None):
self.fileNamePath = ''
self.fileVersion = ''
# open database
self.db = QSqlDatabase.addDatabase("QSQLITE")
self.db.setDatabaseName("processorModel.sqlite")
if not self.db.open():
logging.error(self.__className+ '.__init__ cannot open db')
super().__init__()
# make sure tables are there
self.rib_M = self.RibModel()
self.wing_M = self.WingModel()
def isValid( self, fileName ):
def setFileName( self, fileName ):
def openFile(self):
def readFile(self):
def remTabSpace(self, line):
def remTabSpaceQuot(self, line):
class WingModel(QSqlTableModel, metaclass=Singleton):
def createWingTable(self):
def __init__(self, parent=None):
def syncData(self, q):
class RibModel(QSqlTableModel, metaclass=Singleton):
__className = 'RibModel'
RibNumCol = 1
xribCol = 2
yLECol = 3
yTECol = 4
xpCol = 5
zCol = 6
betaCol = 7
RPCol = 8
WashinCol = 9
def createRibTable(self):
logging.debug(self.__className+'.createRibTable')
query = QSqlQuery()
query.exec("DROP TABLE if exists Rib;")
query.exec("create table if not exists Rib ("
"ID INT PRIMARY KEY,"
"RibNum varchar(50),"
"xrib varchar(50),"
"yLE varchar(50),"
"yTE varchar(50),"
"xp varchar(50),"
"z varchar(50),"
"beta varchar(50),"
"RP varchar(50),"
"Washin varchar(50));")
query.exec("INSERT into Rib (ID) Values( '1' );")
def __init__(self, parent=None):
'''
:method: Constructor
'''
super().__init__()
self.createRibTable()
self.setTable("Rib")
self.select()
self.setEditStrategy(QSqlTableModel.OnFieldChange)
def setupNumRibs(self, halfNumRibs):
logging.debug(self.__className+'.setupNumRibs')
numRows = self.rowCount()
res = self.setData(self.index(1, 1), numRows )
if not res:
modelError = self.lastError()
print('model ErrT : %s' %modelError.type())
print('model Err text : |%s|' %modelError.text())
print()
procM = ProcessorModel()
dbError = procM.db.lastError()
print('db ErrT : %s' %dbError.type())
print('db Err text : |%s|' %dbError.text())
print()
The Singleton Class can be found already here

There is no mystery if you read the docs:
QSqlError QSqlQueryModel::lastError() const
Returns information about the last error that occurred on the
database.
It is clearly indicated that lastError() indicates an error that happens when interacting with the database, but in your case it does not interact since the model first verifies that the QModelIndex is valid, and since yours is not valid then it returns immediately false without doing any transaction with the database.
On the other hand, don't complicate your problem by adding Singleton or other elements that are just noise. It would be recommended that for each question you create an MRE focused only on the problem and thus save us time to help you instead of having to eliminate silly code.

Related

Got the AttributeError: 'FarmerClass' object has no attribute 'farmer_name' in the following code

I am trying to work around autocomplete dropdown combobox which works fine with database. but when i try to fetch data after updating database in runtime I got AttributeError: 'FarmerClass' object has no attribute 'farmer_name'. I tried other available solutions but still error is not solved. as of now, typo and syntax looks fine from the reference code which i was following.
the class which throws error
class FarmerClass(tk.Frame):
def __init__(self, parent, controller):
tk.Frame.__init__(self, parent)
self.veg = []
self.farmer = []
self.buyers = []
self.fetch_data()
self.farmer_name = ttk.Combobox(self)
self.farmer_name['values'] = self.farmer
self.farmer_name.focus()
self.farmer_name.bind('<KeyRelease>', self.check_name)
self.farmer_name.bind('<<ComboboxSelected>>', self.get_data)
self.farmer_name.place(relx=0.028, rely=0.243, width=240, height=24)
self.product = ttk.Combobox(self )
self.product['values'] = self.veg
self.product.bind('<KeyRelease>', self.check_veg)
self.product.place(relx=0.028, rely=0.380,width=240, height=24)
self.buyer = ttk.Combobox(self )
self.buyer['values'] = self.buyers
self.buyer.bind('<KeyRelease>', self.check_buyer)
self.buyer.place(relx=0.028, rely=0.5237,width=240, height=24)
#======================= Entry btn ====================
self.entry_btn = tk.Button(self,Btn_base, text='Entry', command=self.entry_to_bill)
self.entry_btn.place(relx=0.481, rely=0.525,width=134, height=24)
def fetch_data(self, event=None):
cur.execute('SELECT * FROM vegetable ')
for i in cur.fetchall():
self.veg.append(i[0])
cur.execute('SELECT rowid, * FROM farmers ')
for i in cur.fetchall():
self.farmer.append(i[2])
cur.execute('SELECT rowid,name FROM buyers_avail ')
for i in cur.fetchall():
self.buyers.append(i[1])
self.farmer_name.configure(values= self.farmer) # getting error here
self.product.configure(values= self.veg)
self.buyer.configure(values= self.buyers)
def entry_to_bill(self, event=None):
name = self.buyer.get().lower()
cur.execute('SELECT name FROM buyers_avail WHERE name = ? ', [name])
bnames = cur.fetchall()
if bnames:
print(f'buyer {bnames} found')
else:
cur.execute('INSERT INTO buyers_avail (name) VALUES (?)',[name,])
db.commit()
self.buyer.delete(0, tk.END)
self.buyer.focus()
self.fetch_data()
if i try without those lines, farmer_name looks fine, product gets values of buyers and buyer dropdown goes empty.
please ask if anything required related to question.
The fetch_data function accesses farmer_name but you call it before defining farmer_name, which therefore doesn't exist at that point. You need to call fetch_data after defining farmer_name.

How can I change this code : I don't want to use raw SQL but I don't know how can I do

I don't want to use SQL raw. but I don't know how can I change this code.
Looking at the various materials, I tried to find a way not to use SQL raw, but failed. I'm not sure how to change this.
def listSpecificPageWork(request):
current_page = request.GET['current_page']
totalCnt = DjangoBoard.objects.all().count()
print 'current_page=', current_page
boardList = DjangoBoard.objects.raw('SELECT Z.* FROM(SELECT X.*, round((rownum / %s)+0.5) as page FROM(SELECT ID,SUBJECT,NAME, CREATED_DATE, MAIL,MEMO,HITS FROM BOARD_DJANGOBOARD ORDER BY ID DESC)X)Z WHERE page = %s', [rowsPerPage, current_page])
print 'boardList=',boardList, 'count()=', totalCnt
pagingHelperIns = pagingHelper();
totalPageList = pagingHelperIns.getTotalPageList( totalCnt, rowsPerPage)
print 'totalPageList', totalPageList
return render_to_response('listSpecificPage.html', {'boardList': boardList, 'totalCnt': totalCnt, 'current_page':int(current_page), 'totalPageList':totalPageList} )
# -*- coding: utf-8 -*-
class pagingHelper:
"paging helper class"
def getTotalPageList(self, total_cnt, rowsPerPage):
if((total_cnt % rowsPerPage) == 0):
self.total_pages = total_cnt/rowsPerPage;
print 'getTotalPage #1'
else:
self.total_pages = (total_cnt/rowsPerPage) + 1;
print 'getTotalPage #2'
self.totalPageList = []
for j in range(self.total_pages):
self.totalPageList.append(j+1)
return self.totalPageList
def __init__(self):
self.total_pages = 0
self.totalPageList = 0
error : no such column : rownum
I want to change boardList.
see https://docs.djangoproject.com/en/2.2/topics/db/queries/#limiting-querysets
def get_page(page_num,per_page=100):
offset = page_num*per_page
return DjangoDashboard.objects.filter(...).all()[offset:offset+per_page]
get_page(2) # gets the 3rd page (0 based...)
django also provides https://docs.djangoproject.com/en/2.2/topics/pagination/

Iterating a GTK3 Treestore with child nodes in python

im trying to search a GTK 3 treestore for a string. The treestore has 4 columns,and is for a treeview widget that has callapsible nodes. im creating the nodes with this function:
def AddItem(self,ParentIter,txt,datapath='',projName=Project):
self.store = self.builder.get_object('theTreeStore')
NodeId = secrets.token_hex(8)
if ParentIter == None:
ParentNodeId = ''
else:
ParentNodeId = self.store.get_value(ParentIter, 2)
treeEntry = ['%s' %ParentNodeId,'%s' %txt,'%s' %NodeId,'%s' %datapath]
node = self.store.append(ParentIter, treeEntry) <<<<<<<<<<<<<
self.view = self.builder.get_object('Tree')
self.view.set_model(self.store)
# table nodes(tParentNodeID ,tNodeTxt ,tNodeID ,tDataPath );
sql = "INSERT INTO %s (tParentNodeID ,tNodeTxt ,tNodeID ,tDataPath ) VALUES ('%s','%s','%s','%s')" %(projName,ParentNodeId,txt,NodeId,datapath)
self.cursor.execute(sql)
self.mariadb_connection.commit()
for x in self.cursor:
print(x)
return(node)
as you can see the data in the tree is nested in its parent.
now i need to somehow search the treestore for a row that contains a certain NodeId string. Ive read the gtk docs over and over but i cant quite figure out what to do. im guessing i need to use following methods:
store.get_iter()
store.iter_children()
but idk everything i try only returns the root nodes no children.
i basically want a search function that will recursively search each node and its children,and their children for a string. something like this:
def GetRowbyNodeID(nodeid):
for row in treestore:
if row[1]==nodeid:
return(row)
for children in row:
if children[1] == nodeid
return(children)
The code is in multiple files, i can post any functions relevant if needed.
GtkTreeStore implements GtkTreeModel interface. Thus you can use the following methods:
iter = store.get_iter() to obtain an iterator
chld_iter = iter.get_children()to obtain an iterator over children elements (please note, it's an iter's method!)
I'd also recommend reading this tutorial. "The Model" section contains all you need on iterating over the model (spoiler: search for print_tree_store)
Got it all working. thanks again. im posting the relevant code just in case anyone else could use it.
def SearchTreeRows(self,store, treeiter, searchstr):
print("\nsearch>%s"%searchstr)
while treeiter != None:
if store[treeiter][2] ==searchstr:
print("found in:%s"%str(store[treeiter][:]))
return(treeiter)
break
print("searched:%s"%str(store[treeiter][:]))
if store.iter_has_child(treeiter):
childiter = store.iter_children(treeiter)
ret = self.SearchTreeRows(store, childiter, searchstr)
if ret is not None:
return ret
treeiter = store.iter_next(treeiter)
def NodeId2Tree(self,nodeid):
self.store = self.builder.get_object('theTreeStore')
rootiter = self.store.get_iter_first()
row = self.SearchTreeRows(self.store, rootiter,nodeid)
return(row)
def LoadProject(self):
global Project
global ProjSel
sql = "SHOW TABLES"
self.cursor.execute(sql)
tbls = []
for x in self.cursor:
tbls.append(x)
diag = self.builder.get_object('ProjectChooser')
self.combo = Gtk.ComboBox()
ls =Gtk.ListStore(str)
for tble in tbls:
strg ="%s" %tble
ls.append(tble)
self.combo.set_model(ls)
cellr = Gtk.CellRendererText()
self.combo.pack_start(cellr,True)
self.combo.add_attribute(cellr, 'text', 0)
diag.vbox.pack_start(self.combo, True, True, 5)
diag.show_all()
response = diag.run()
self.combo.destroy()
print(ProjSel)
Project = ProjSel
ProjSel = ''
view = self.builder.get_object('Tree')
self.store.clear()
view.set_model(self.store)
sql = "SELECT tParentNodeId,tNodeTxt,tNodeId FROM %s"%(Project)
self.cursor.execute(sql)
for x in self.cursor:
parid = x[0]
nodtxt = x[1]
nodid =x[2]
if parid == '':
treeEntry = ['%s' %parid, '%s' %nodtxt, '%s' %nodid, '']
node = self.store.append(None, treeEntry) #root nodes
else:
treeEntry = ['%s' %parid, '%s' %nodtxt, '%s' %nodid, '']
n2id = self.NodeId2Tree(parid)
node = self.store.append(n2id, treeEntry)
print("got return:%s For:%s"%(n2id,treeEntry[0]))
view.set_model(self.store)
#select * where parentid == none >> get root nodes ???? or parse line by line

python- sqlite3.OperationalError: near ",": syntax error"

This isn't my code; I got it from https://www.youtube.com/channel/UC4KX0hatvRrOVy_D0nPlusg. The author didn't have the source code so I just had to type it up from the video. His worked fine but I kept getting this error:
File "D:\ProgramDevelopment\Python\Project\Python_GUI_IDEL\PythonDatabaseYoutube.py", line 45, in run_query
query_result= cursor.execute(query,parameters)
sqlite3.OperationalError: near ",": syntax error"
Link in github: https://github.com/ahmed-aya/Python_database/blob/master/Python_Database
from tkinter import *
from tkinter import ttk
import sqlite3
class Product(object):
def __init__(self,wind):
self.wind=wind
self.wind.title('IT products')
frame = LabelFrame (self.wind,text= 'Add new record')
frame.grid (row=0,column=1)
Label(frame,text='Name:').grid(row=1,column=1)
self.name =Entry(frame)
self.name.grid(row=1,column=2)
Label(frame,text='Price:').grid(row=2,column=1)
self.price =Entry(frame)
self.price.grid(row=2,column=2)
ttk.Button(frame,text='Add record',command=self.adding).grid(row=3,column=2)
self.message=Label(text='',fg='red')
self.message.grid(row=3,column=0)
self.tree=ttk.Treeview(height=10,column=2)
self.tree.grid(row=4,column=0,columnspan=2)
self.tree.heading('#0',text='Name',anchor=W)
self.tree.heading(2,text='Price',anchor=W)
ttk.Button(text='Delete record',command=self.deleting).grid(row=5,column=0)
ttk.Button(text='Edit record',command=self.editing).grid(row=5,column=1)
self.viewing_records()
def run_query (self, query, parameters=()):
with sqlite3.connect('database.db') as conn:
cursor = conn.cursor()
query_result= cursor.execute(query,parameters)
conn.commit()
return query_result
def viewing_records(self):
records = self.tree.get_children()
for element in records:
self.tree.delete(element)
query ='SELECT * FROM product ORDER BY name DESC'
db_rows = self.run_query (query)
for row in db_rows:
self.tree.insert('',0,text=row[1], values = row[2])
def validation (self):
return len (self.name.get()) !=0 and len (self.price.get()) !=0
def adding (self):
if self.validation():
query ='INSERT INTO product VALUES (NULL,?,?)'
parameters =(self.name.get(),self.price.get())
self.run_query(query,parameters)
self.message ['text'] = 'Record {} added'.format (self.name.get())
self.name.delete(0,END)
self.price.delete(0,END)
else:
self.message['text']='name field or price is empty'
self.viewing_records()
def deleting (self):
self.message['text']=''
try:
self.tree.item (self.tree.selection())['text']
except IndexError as e:
self.message['text']='Please, select recoard'
return
self.message['text']=''
name=self.tree.item (self.tree.selection())['text']
query='DELETE FROM product WHERE name=?'
self.run_query(query,(name,))
self.message['text']='Record {} deleted.'.format(name)
self.viewing_records()
def editing(self):
self.message['text']=""
try:
self.tree.item (self.tree.selection())['values'][0]
except IndexError as e:
self.message['text']='Please select record'
return
name = self.tree.item (self.tree.selection())['text']
old_price = self.tree.item (self.tree.selection())['values'][0]
self.edit_wind= Toplevel()
self.edit_wind.title('Edit Window')
Label (self.edit_wind,text='Old name: ').grid(row=0,column=1)
Entry (self.edit_wind,textvariable=StringVar(self.edit_wind,value=name),state='readonly').grid(row=0,column=2)
Label (self.edit_wind,text='New name: ').grid(row=1,column=1)
new_name = Entry(self.edit_wind)
new_name.grid(row=1,column=2)
Label (self.edit_wind,text='Old price: ').grid(row=2,column=1)
Entry (self.edit_wind,textvariable = DoubleVar(self.edit_wind,value=old_price),state='readonly').grid(row=2,column=2)
Label (self.edit_wind,text='New price: ').grid(row=3,column=1)
new_price=Entry(self.edit_wind)
new_price.grid(row=3,column=2)
Button(self.edit_wind,text='save changes', command=lambda:self.edit_records(new_name.get(),name,new_price.get(),old_price)).grid(row=4,column=2,sticky=W)
self.edit_wind.mainloop()
def edit_records(self, new_name,name,new_price,old_price):
query = 'UPDATE product SET name=?,price,=? WHERE name=? AND price =?'
parameters = (new_name,new_price,name,old_price)
self.run_query (query,parameters)
self.edit_wind.destroy()
self.message['text']='Record {} changed.'.format(name)
self.viewing_records()
if __name__== '__main__':
wind=Tk()
application = Product(wind)
wind.mainloop()
As your error says, you have a typo.
query = 'UPDATE product SET name=?,price,=? WHERE name=? AND price =?'
^ extra comma here

Error message "MemoryError" in Python

Here's my problem: I'm trying to parse a big text file (about 15,000 KB) and write it to a MySQL database. I'm using Python 2.6, and the script parses about half the file and adds it to the database before freezing up. Sometimes it displays the text:
MemoryError.
Other times it simply freezes. I figured I could avoid this problem by using generator's wherever possible, but I was apparently wrong.
What am I doing wrong?
When I press Ctrl + C to keyboard interrupt, it shows this error message:
...
sucessfully added vote # 2281
sucessfully added vote # 2282
sucessfully added vote # 2283
sucessfully added vote # 2284
floorvotes_db.py:35: Warning: Data truncated for column 'vote_value' at row 1
r['bill ID'] , r['last name'], r['vote'])
Traceback (most recent call last):
File "<stdin>", line 1, in <module>
File "floorvotes_db.py", line 67, in addAllFiles
addFile(file)
File "floorvotes_db.py", line 61, in addFile
add(record)
File "floorvotes_db.py", line 35, in add
r['bill ID'] , r['last name'], r['vote'])
File "build/bdist.linux-i686/egg/MySQLdb/cursors.py", line 166, in execute
File "build/bdist.linux-i686/egg/MySQLdb/connections.py", line 35, in defaulte rrorhandler
KeyboardInterrupt
import os, re, datetime, string
# Data
DIR = '/mydir'
tfn = r'C:\Documents and Settings\Owner\Desktop\data.txt'
rgxs = {
'bill number': {
'rgx': r'(A|S)[0-9]+-?[A-Za-z]* {50}'}
}
# Compile rgxs for speediness
for rgx in rgxs: rgxs[rgx]['rgx'] = re.compile(rgxs[rgx]['rgx'])
splitter = rgxs['bill number']['rgx']
# Guts
class floor_vote_file:
def __init__(self, fn):
self.iterdata = (str for str in
splitter.split(open(fn).read())
if str and str <> 'A' and str <> 'S')
def iterVotes(self):
for record in self.data:
if record: yield billvote(record)
class billvote(object):
def __init__(self, section):
self.data = [line.strip() for line
in section.splitlines()]
self.summary = self.data[1].split()
self.vtlines = self.data[2:]
self.date = self.date()
self.year = self.year()
self.votes = self.parse_votes()
self.record = self.record()
# Parse summary date
def date(self):
d = [int(str) for str in self.summary[0].split('/')]
return datetime.date(d[2],d[0],d[1]).toordinal()
def year(self):
return datetime.date.fromordinal(self.date).year
def session(self):
"""
arg: 2-digit year int
returns: 4-digit session
"""
def odd():
return divmod(self.year, 2)[1] == 1
if odd():
return str(string.zfill(self.year, 2)) + \
str(string.zfill(self.year + 1, 2))
else:
return str(string.zfill(self.year - 1, 2))+ \
str(string.zfill(self.year, 2))
def house(self):
if self.summary[2] == 'Assembly': return 1
if self.summary[2] == 'Senate' : return 2
def splt_v_line(self, line):
return [string for string in line.split(' ')
if string <> '']
def splt_v(self, line):
return line.split()
def prse_v(self, item):
"""takes split_vote item"""
return {
'vote' : unicode(item[0]),
'last name': unicode(' '.join(item[1:]))
}
# Parse votes - main
def parse_votes(self):
nested = [[self.prse_v(self.splt_v(vote))
for vote in self.splt_v_line(line)]
for line in self.vtlines]
flattened = []
for lst in nested:
for dct in lst:
flattened.append(dct)
return flattened
# Useful data objects
def record(self):
return {
'date' : unicode(self.date),
'year' : unicode(self.year),
'session' : unicode(self.session()),
'house' : unicode(self.house()),
'bill ID' : unicode(self.summary[1]),
'ayes' : unicode(self.summary[5]),
'nays' : unicode(self.summary[7]),
}
def iterRecords(self):
for vote in self.votes:
r = self.record.copy()
r['vote'] = vote['vote']
r['last name'] = vote['last name']
yield r
test = floor_vote_file(tfn)
import MySQLdb as dbapi2
import floorvotes_parse as v
import os
# Initial database crap
db = dbapi2.connect(db=r"db",
user="user",
passwd="XXXXX")
cur = db.cursor()
if db and cur: print "\nConnected to db.\n"
def commit(): db.commit()
def ext():
cur.close()
db.close()
print "\nConnection closed.\n"
# DATA
DIR = '/mydir'
files = [DIR+fn for fn in os.listdir(DIR)
if fn.startswith('fvote')]
# Add stuff
def add(r):
"""add a record"""
cur.execute(
u'''INSERT INTO ny_votes (vote_house, vote_date, vote_year, bill_id,
member_lastname, vote_value) VALUES
(%s , %s , %s ,
%s , %s , %s )''',
(r['house'] , r['date'] , r['year'],
r['bill ID'] , r['last name'], r['vote'])
)
#print "added", r['year'], r['bill ID']
def crt():
"""create table"""
SQL = """
CREATE TABLE ny_votes (openleg_id INT UNSIGNED NOT NULL AUTO_INCREMENT PRIMARY KEY,
vote_house int(1), vote_date int(5), vote_year int(2), bill_id varchar(8),
member_lastname varchar(50), vote_value varchar(10));
"""
cur.execute(SQL)
print "\nCreate ny_votes.\n"
def rst():
SQL = """DROP TABLE ny_votes"""
cur.execute(SQL)
print "\nDropped ny_votes.\n"
crt()
def addFile(fn):
"""parse and add all records in a file"""
n = 0
for votes in v.floor_vote_file(fn).iterVotes():
for record in votes.iterRecords():
add(record)
n += 1
print 'sucessfully added vote # ' + str(n)
def addAllFiles():
for file in files:
addFile(file)
if __name__=='__main__':
rst()
addAllFiles()
Generators are a good idea, but you seem to miss the biggest problem:
(str for str in splitter.split(open(fn).read()) if str and str <> 'A' and str <> 'S')
You're reading the whole file in at once even if you only need to work with bits at a time. You're code is too complicated for me to fix, but you should be able to use file's iterator for your task:
(line for line in open(fn))
I noticed that you use a lot of slit() calls. This is memory consuming, according to http://mail.python.org/pipermail/python-bugs-list/2006-January/031571.html . You can start investigating this.
Try to comment out add(record) to see if the problem is in your code or on the database side. All the records are added in one transaction (if supported) and maybe this leads to a problem if it get too many records. If commenting out add(record) helps, you could try to call commit() from time to time.
This isn't a Python memory issue, but perhaps it's worth thinking about. The previous answers make me think you'll sort that issue out quickly.
I wonder about the rollback logs in MySQL. If a single transaction is too large, perhaps you can checkpoint chunks. Commit each chunk separately instead of trying to rollback a 15MB file's worth.

Categories