I need your help in order to solve this problem.
I am trying to enter a line in a database where the program has to find a material X in the database and then get the quantity value. After that, the program creates a new line where it adds the stock entered by the user + the current stock in a new line. The program works as long as the last line in the database is the same material X, but in case the last line is for material Y, then it raises this error.
Here I attach the code:
from tkinter import *
from tkinter import ttk
from datetime import datetime
import sqlite3
class Main:
db_name = 'materiales.db'
def __init__(self,window):
self.wind = window
self.wind.title('Stock App')
#create frame
frame = LabelFrame(self.wind, text = 'Add stock')
frame.grid(row = 0, column = 0, columnspan = 3, pady = 20)
# Name Input
Label(frame, text = 'Name: ').grid(row = 1, column = 0)
self.name = Entry(frame)
self.name.focus()
self.name.grid(row = 1, column = 1)
# Quantity Input
Label(frame, text = 'Quantity: ').grid(row = 2, column = 0)
self.quantity = Entry(frame)
self.quantity.grid(row = 2, column = 1)
# Button Add Stock
ttk.Button(frame, text = 'Add Stock', command = self.add_stock).grid(row = 3, columnspan = 2, sticky = W + E)
#Log Message
self.message = Label(text = '', fg = 'red')
self.message.grid(row = 3, column = 0, columnspan = 2, sticky = W + E)
#Button Search Stocks
ttk.Button(text = 'Search Stocks', command = self.search_stocks).grid(row = 5, column = 0, columnspan = 3, pady = 20, sticky = W + E)
def run_query(self, query, parameters = ()):
with sqlite3.connect(self.db_name) as conn:
cursor = conn.cursor()
result = cursor.execute(query, parameters)
conn.commit()
return result
def validation(self):
return len(self.name.get()) != 0 and len(self.quantity.get()) !=0
def add_stock(self):
time = datetime.now().strftime("%B %d, %Y")
hour = datetime.now().strftime("%I:%M%p")
query = 'SELECT totalstock FROM stocks WHERE name = ? AND MovementID = ( SELECT max( MovementID ) FROM stocks)'
parameters = (self.name.get(),)
lastrecord = self.run_query(query, parameters)
total = lastrecord.fetchone()[0]
total += int(self.quantity.get())
if self.validation():
query = 'INSERT INTO stocks VALUES(NULL, ?, ?, ?, ?, ?)'
parameters = (self.name.get(), self.quantity.get(), total, time, hour)
self.run_query(query, parameters)
self.message['text'] = 'Stock for {} added succesfully'.format(self.name.get())
self.name.delete(0, END)
self.quantity.delete(0, END)
else:
self.message['text'] = 'Name and Quantity required'
self.get_product()
def search_stocks(self):
self.edit_wind = Toplevel()
self.edit_wind.title = 'Search Stocks'
#Name Product
Label(self.edit_wind, text = 'Name: ').grid(row = 0, column = 1)
name = Entry(self.edit_wind)
name.grid(row = 0, column = 2)
Button(self.edit_wind, text = 'Search', command = lambda: self.edit_records(new_name.get(), name, new_price.get(), old_price)).grid(row = 4, column = 2, sticky = W)
def edit_records(self, name):
query = 'SELECT totalstock FROM stocks WHERE name = ? AND MovementID = ( SELECT max( MovementID ) FROM stocks)'
parameters = (name)
self.run_query(query, parameters)
self.edit_wind.destroy()
self.message['text'] = 'Total stock is {}'.format(totalstock)
self.get_product()
if __name__ == '__main__':
window = Tk()
application = Main(window)
window.mainloop()
Here I attach the complete error:
Exception in Tkinter callback
Traceback (most recent call last):
File "C:\Users\Xavi\AppData\Local\Programs\Python\Python39\lib\tkinter\__init__.py", line 1884, in __call__
return self.func(*args)
File "C:\Users\Xavi\Desktop\Program\stock\stocklist.py", line 58, in add_stock
total = lastrecord.fetchone()[0]
TypeError: 'NoneType' object is not subscriptable
>>>
Happy new year 2021 and thanks for your help
This line causes the error if no records match the selection criteria in the query:
total = lastrecord.fetchone()[0]
If no records match then lastrecord.fetchone()
evaluates to None
, resulting in the TypeError
.
You could handle this by using a try/except block:
try:
total = lastrecord.fetchone()[0]
except TypeError:
total = 0
or an if/else:
row = lastrecord.fetchone()
if row is None:
total = 0
else:
total = row[0]
or more succintly
row = lastrecord.fetchone()
total = row[0] if row is not None else 0