PyQT: Using attributes from SQLite query - python

I am confused as to how I can use certain attributes that are returned after a query to a local SQLite database. I can populate a qlistwidget with one of the attributes but I do not know how to get the other attributes when a user clicks on the listwidget item.
The following code was created using Eric which pre populates some of the signals and slots
#pyqtSignature("QString")
def on_searchText_textEdited(self, p0):
"""
Slot documentation goes here.
"""
# TODO: not implemented yet
self.resultsList.clear()
self.searchItem = self.searchText.text()
self.search()
#pyqtSignature("QListWidgetItem*")
def on_resultsList_itemClicked(self, item):
"""
Slot documentation goes here.
"""
# TODO: not implemented yet
result = str(item.text())
QMessageBox.about(self, "Clicked Item", "%s")%(result)
#pyqtSignature("")
def on_cancelButton_clicked(self):
"""
Slot documentation goes here.
"""
self.close()
def search(self):
conn = sqlite3.connect("C:\\file.sqlite")
cur = conn.cursor()
sqlqry = "SELECT name, number, size FROM lookup WHERE name LIKE '%s' LIMIT 100;"%("%"+self.searchItem+"%")
try:
c = cur.execute(sqlqry)
data = c.fetchall()
for i in data:
self.resultsList.addItem(i[0])
except sqlite3.Error, e:
QMessageBox.about(self, "Error message", "Error")
So my resultsList gets populated when the user enters text into the line edit but then when a user clicks on an item I get an error with the messagebox saying something about a NoneType and str.
However, what I really need to use are the second and third attributes for somewhere else in my code.
So how do I select that attributes through the itemClicked signal and create two new variables?
i hope that makes sense, it has been a long day going round in circles

You just need to query from the database again and work with the new row.
#pyqtSignature("QListWidgetItem*")
def on_resultsList_itemClicked(self, item):
"""
Slot documentation goes here.
"""
result = str(item.text())
QMessageBox.about(self, "Clicked Item", "%s")%(result)
conn = sqlite3.connect("C:\\file.sqlite")
cur = conn.cursor()
sqlqry = "SELECT name, number, size FROM lookup WHERE name = '%s' LIMIT 1;"%(result)
try:
c = cur.execute(sqlqry)
data = c.fetchone()
# Do something with data
except sqlite3.Error, e:
QMessageBox.about(self, "Error fetching %s"%name, "Error")
Obviously, this doesn't deal with the database santisation issues you might have, and assumes that name is unique in the database.

Related

TypeError sqlite python

I am new to sqlite in python and I am trying to do the following:
Extract a certain value from a row in a table and compare it to 100 (it's an INT type normally).
school is a table where I have the following attributes: id, class, nbstudent, nbteachers, nbrepresentative
I use the following function:
def select_school_value(conn, class,m):
"""
Query school by class
"""
cur = conn.cursor()
cur.execute("SELECT * FROM school WHERE class=?", (class,))
record = cur.fetchone()
return record[m]
The function's parameter m is just a number that depends on which attribute I want to extract for the comparaison: nbstudent is m=2, nbteacher is m=3..
When I use my function select_school_value() and compare the returned value with 100, I have a TypeError, the return is a NoneType.
How can I have a integer type return (the type of the attribute I need)?
Thank you in advance.
I guess the issue is in class parameter that you pass to your function and query. Rename it somehow, because Python treats it like a pointer to some class within python code.
Also you have that class=? part which means actuallly "find a class which equals '?'". It should be rewritten too.
I suggest trying this:
def select_school_value(conn,cl,m):
"""
Query school by class
"""
cur = conn.cursor()
cur.execute("SELECT * FROM school WHERE class={}".format(cl))
record = cur.fetchone()
return record[m]

__init__() missing 1 required positional argument: 'receiver'?

Im trying to get the data of a word through database with sqlite3 and python but when i try to call the read_from_db function, i have this error _init__() missing 1 required positional argument: 'receiver'. I cant seem to find what happened
heres the code
conn = sqlite3.connect('yeet1.db')
cursor = conn.cursor()
class Ui_WordWindow(object):
def __init__(self, receiver): #Inherit user-input word from another window
self.receiver = receiver
print(self.receiver) #Checking if it worked correctly
def read_From_db(self): #Read and print out data of user-input word
cursor.execute(('SELECT * FROM mytable WHERE Meaning = ?', self.receiver))
data = cursor.fetchall()
print(data)
window2 = Ui_WordWindow()
window2.read_From_db()
cursor.close()
conn.close
You declare the __init__ method of the class Ui_WordWindow like so:
def __init__(self, receiver): #Inherit user-input word from another window
And it does have a parameter receiver. The error you get indicates that when constructing a Ui_WordWindow you should provide exactly one parameter and that should be the value for receiver.
I.e. this line:
window2 = Ui_WordWindow()
Should in fact be:
window2 = Ui_WordWindow(receiver)
where receiver is a valid value for receiver.
The receiver object = "some value"
conn = sqlite3.connect('yeet1.db')
cursor = conn.cursor()
class Ui_WordWindow(object):
def __init__(self, receiver): #Inherit user-input word from another window
self.receiver = receiver
print(self.receiver) #Checking if it worked correctly
#when you print self.receiver it means the value which you are passing say for example "test"
def read_From_db(self): #Read and print out data of user-input word
cursor.execute(('SELECT * FROM mytable WHERE Meaning = ?', "test"))
# now the query becomes select * from mytable where meaning = 'test'
# the value 'test' is being passed by the receiver object and you need to provide that value
data = cursor.fetchall()
print(data)
window2 = Ui_WordWindow(receiver) # which has some value ex 'test'
window2.read_From_db()
cursor.close()
conn.close
you need to brush up on object oriented approach.
try reading from this: python object oriented

Connection and Cursor inside a class in psycopg2

I would like to use the connection and cursor classes inside a custom made class. I would also like to inherit all the methods associated with the connection and cursor classes. I have done some research on it and found docs and this question related to my problem. I have some code that is working partly. i.e I can insert and update the database. However, I cannot select from the database because doing so returns none even when the row is in the database. Here is my code
from datetime import datetime, timedelta
import psycopg2
import psycopg2.extensions
class DataBase():
"""A class used to create tables in the database. Inherits from
psycopg2.extensions.connection in order to gain access to the cursor,
commit, close, and many other features from the pyscopg module.
"""
def __init__(self):
self.my_connection = psycopg2.connect(database="public", user="public",
password="general", host="127.0.0.1",
port="5432")
self.my_cursor = self.my_connection.cursor()
def query_database(self, sql_statement, *args):
return self.my_cursor.execute(sql_statement, *args)
def commit_query(self):
return self.my_connection.commit()
def fetch_one(self, sql_statement, *args):
result = self.query_database(sql_statement, *args)
if result is None:
return False
return result.fetchone()
def fetch_all(self, sql_statement, *args):
result = self.query_database(sql_statement, *args)
if result is None:
return False
return result.fetchall()
def __del__(self):
self.my_cursor.close()
self.my_connection.close()
############################################################################
class CreateTables(DataBase):
def create_user_table(self):
"""Helper function used to create the user_table"""
sql_statement = '''CREATE TABLE IF NOT EXISTS USERS
(ID SERIAL PRIMARY KEY,
FIRSTNAME TEXT NOT NULL,
LASTNAME TEXT NOT NULL,
USERNAME TEXT NOT NULL UNIQUE,
EMAIL TEXT NOT NULL UNIQUE,
PASSWORD TEXT NOT NULL,
DATETIMEREGISTERED TIMESTAMP NOT NULL);'''
user_table = DataBase.query_database(self, sql_statement)
DataBase.commit_query(self)
return user_table
def create_entries_table(self):
"""Helper function used to create an entries table."""
sql_statement = '''CREATE TABLE IF NOT EXISTS ENTRIES
(ID SERIAL PRIMARY KEY,
TITLE TEXT NOT NULL,
DRINK TEXT NOT NULL,
DATEOFORDER TIMESTAMP NOT NULL,
TIMETODELIVERY TIMESTAMP NOT NULL,
SETREMINDER TIMESTAMP NOT NULL,
USERID INT REFERENCES USERS ON DELETE CASCADE);'''
entries_table = DataBase.query_database(self, sql_statement)
DataBase.commit_query(self)
print("entries table created.")
return entries_table
# test = CreateTables() This is working well
# print(test.create_entries_table())
#####################################################################
class OperateDatabase(CreateTables):
def create_user(self, email, username, *args):
"""Helper function used to create a user"""
sql_statement = """SELECT ID FROM USERS WHERE EMAIL = %s OR
USERNAME = %s;"""
user_in_database = CreateTables.fetch_one(self, sql_statement,
(email, username,))
print("the user in database is :>>", user_in_database)
sql_statement2 = """INSERT INTO USERS (FIRSTNAME, LASTNAME, USERNAME,
EMAIL, PASSWORD, DATETIMEREGISTERED)
VALUES (%s, %s, %s, %s, %s, %s);"""
if not user_in_database:
CreateTables.query_database(self,sql_statement2, *args)
CreateTables.commit_query(self)
return True
return False
data = ("Jkdai", "Jkdal", "Jkdai", "jkdai#gmail.com", "password", datetime.now())
test = OperateDatabase()
print(test.create_user("jkdai#gmail.com", "jkdai", data))
#Inserts the user the very first time implying the insert statement is working
#raises an integrity error the second time implying the select statement is not working.
#Also the print statement defaults to false when it is supposed to return the user's id.
cursor.execute() returns a vendor-defined value (it's not specified in the db-api spec), and for pyscopg2 it is actually documented as returning None indeed, so this:
def query_database(self, sql_statement, *args):
return self.my_cursor.execute(sql_statement, *args)
def fetch_one(self, sql_statement, *args):
result = self.query_database(sql_statement, *args)
if result is None:
return False
return result.fetchone()
will obviously not work as you expect. You could return self.my_cursor() from query_database() instead, ie:
def query_database(self, sql_statement, *args):
self.my_cursor.execute(sql_statement, *args)
return self.my_cursor
def fetch_one(self, sql_statement, *args):
cursor = self.query_database(sql_statement, *args)
return cursor.fetchone()
but there's a fundamental flaw with this code, which is that it's not reentrant (nor thread safe FWIW). Actually, your class should NOT store a cursor as part of it's state and reuse it over and over (db-api cursors are not meant to be used that way) but create a new cursor for every operation (which is the indented use).
Also, you should not rely on __del__(self) to close your connection. The __del__() method is not a proper C++/Java style finalizer and is not even garanteed to be called when the object is collected. Actually, trying to wrap a db connection and cursor in a class is usually not a good idea, at least not this way.

What is the proper way to delineate modules and classes in Python?

I am new to Python, and I'm starting to learn the basics of the code structure. I've got a basic app that I'm working on up on my Github.
For my simple app, I'm create a basic "Evernote-like" service which allows the user to create and edit a list of notes. In the early design, I have a Note object and a Notepad object, which is effectively a list of notes. Presently, I have the following file structure:
Notes.py
|
|------ Notepad (class)
|------ Note (class)
From my current understanding and implementation, this translates into the "Notes" module having a Notepad class and Note class, so when I do an import, I'm saying "from Notes import Notepad / from Notes import Note".
Is this the right approach? I feel, out of Java habit, that I should have a folder for Notes and the two classes as individual files.
My goal here is to understand what the best practice is.
As long as the classes are rather small put them into one file.
You can still move them later, if necessary.
Actually, it is rather common for larger projects to have a rather deep hierarchy but expose a more flat one to the user. So if you move things later but would like still have notes.Note even though the class Note moved deeper, it would be simple to just import note.path.to.module.Note into notes and the user can get it from there. You don't have to do that but you can. So even if you change your mind later but would like to keep the API, no problem.
I've been working in a similar application myself. I can't say this is the best possible approach, but it served me well. The classes are meant to interact with the database (context) when the user makes a request (http request, this is a webapp).
# -*- coding: utf-8 -*-
import json
import datetime
class Note ():
"""A note. This class is part of the data model and is instantiated every
time there access to the database"""
def __init__(self, noteid = 0, note = "", date = datetime.datetime.now(), context = None):
self.id = noteid
self.note = note
self.date = date
self.ctx = context #context holds the db connection and some globals
def get(self):
"""Get the current object from the database. This function needs the
instance to have an id"""
if id == 0:
raise self.ctx.ApplicationError(404, ("No note with id 0 exists"))
cursor = self.ctx.db.conn.cursor()
cursor.execute("select note, date from %s.notes where id=%s" %
(self.ctx.db.DB_NAME, str(self.id)))
data = cursor.fetchone()
if not data:
raise self.ctx.ApplicationError(404, ("No note with id "
+ self.id + " was found"))
self.note = data[0]
self.date = data[1]
return self
def insert(self, user):
"""This function inserts the object to the database. It can be an empty
note. User must be authenticated to add notes (authentication handled
elsewhere)"""
cursor = self.ctx.db.conn.cursor()
query = ("insert into %s.notes (note, owner) values ('%s', '%s')" %
(self.ctx.db.DB_NAME, str(self.note), str(user['id'])))
cursor.execute(query)
return self
def put(self):
"""Modify the current note in the database"""
cursor = self.ctx.db.conn.cursor()
query = ("update %s.notes set note = '%s' where id = %s" %
(self.ctx.db.DB_NAME, str(self.note), str(self.id)))
cursor.execute(query)
return self
def delete(self):
"""Delete the current note, by id"""
if self.id == 0:
raise self.ctx.ApplicationError(404, "No note with id 0 exists")
cursor = self.ctx.db.conn.cursor()
query = ("delete from %s.notes where id = %s" %
(self.ctx.db.DB_NAME, str(self.id)))
cursor.execute(query)
def toJson(self):
"""Returns a json string of the note object's data attributes"""
return json.dumps(self.toDict())
def toDict(self):
"""Returns a dict of the note object's data attributes"""
return {
"id" : self.id,
"note" : self.note,
"date" : self.date.strftime("%Y-%m-%d %H:%M:%S")
}
class NotesCollection():
"""This class handles the notes as a collection"""
collection = []
def get(self, user, context):
"""Populate the collection object and return it"""
cursor = context.db.conn.cursor()
cursor.execute("select id, note, date from %s.notes where owner=%s" %
(context.db.DB_NAME, str(user["id"])))
note = cursor.fetchone()
while note:
self.collection.append(Note(note[0], note[1],note[2]))
note = cursor.fetchone()
return self
def toJson(self):
"""Return a json string of the current collection"""
return json.dumps([note.toDict() for note in self.collection])
I personally use python as a "get it done" language, and don't bother myself with details. This shows in the code above. However one piece of advice: There are no private variables nor methods in python, so don't bother trying to create them. Make your life easier, code fast, get it done
Usage example:
class NotesCollection(BaseHandler):
#tornado.web.authenticated
def get(self):
"""Retrieve all notes from the current user and return a json object"""
allNotes = Note.NotesCollection().get(self.get_current_user(), settings["context"])
json = allNotes.toJson()
self.write(json)
#protected
#tornado.web.authenticated
def post(self):
"""Handles all post requests to /notes"""
requestType = self.get_argument("type", "POST")
ctx = settings["context"]
if requestType == "POST":
Note.Note(note = self.get_argument("note", ""),
context = ctx).insert(self.get_current_user())
elif requestType == "DELETE":
Note.Note(id = self.get_argument("id"), context = ctx).delete()
elif requestType == "PUT":
Note.Note(id = self.get_argument("id"),
note = self.get_argument("note"),
context = ctx).put()
else:
raise ApplicationError(405, "Method not allowed")
By using decorators I'm getting user authentication and error handling out of the main code. This makes it clearer and easier to mantain.

how to get entities which don't have certain attribute in datastore

I'm trying to make an appraisal system
This is my class
class Goal(db.Expando):
GID = db.IntegerProperty(required=True)
description = db.TextProperty(required=True)
time = db.FloatProperty(required=True)
weight = db.IntegerProperty(required=True)
Emp = db.UserProperty(auto_current_user=True)
Status = db.BooleanProperty(default=False)
Following things are given by employee,
class SubmitGoal(webapp.RequestHandler):
def post(self):
dtw = simplejson.loads(self.request.body)
try:
maxid = Goal.all().order("-GID").get().GID + 1
except:
maxid = 1
try:
g = Goal(GID=maxid, description=dtw[0], time=float(dtw[1]), weight=int(dtw[2]))
g.put()
self.response.out.write(simplejson.dumps("Submitted"))
except:
self.response.out.write(simplejson.dumps("Error"))
Now, here Manager checks the goals and approve it or not.. if approved then status will be stored as true in datastore else false
idsta = simplejson.loads(self.request.body)
try:
g = db.Query(Goal).filter("GID =", int(idsta[0])).get()
if g:
if idsta[1]:
g.Status=True
try:
del g.Comments
except:
None
else:
g.Status=False
g.Comments=idsta[2]
db.put(g)
self.response.out.write(simplejson.dumps("Submitted"))
except:
self.response.out.write(simplejson.dumps("Error"))
Now, this is where im stuck..."filter('status=',True)".. this is returning all the entities which has status true.. means which are approved.. i want those entities which are approved AND which have not been assessed by employee yet..
def get(self):
t = []
for g in Goal.all().filter("Status = ",True):
t.append([g.GID, g.description, g.time, g.weight, g.Emp])
self.response.out.write(simplejson.dumps(t))
def post(self):
idasm = simplejson.loads(self.request.body)
try:
g = db.Query(Goal).filter("GID =", int(idasm[0])).get()
if g:
g.AsmEmp=idasm[1]
db.put(g)
self.response.out.write(simplejson.dumps("Submitted"))
except:
self.response.out.write(simplejson.dumps("Error"))
How am I supposed to do this? as I know that if I add another filter like "filter('AsmEmp =', not None)" this will only return those entities which have the AsmEmp attribute what I need is vice versa.
You explicitly can't do this. As the documentation states:
It is not possible to query for entities that are missing a given property.
Instead, create a property for is_assessed which defaults to False, and query on that.
could you not simply add another field for when employee_assessed = db.user...
and only populate this at the time when it is assessed?
The records do not lack the attribute in the datastore, it's simply set to None. You can query for those records with Goal.all().filter('status =', True).filter('AsmEmp =', None).
A few incidental suggestions about your code:
'Status' is a rather unintuitive name for a boolean.
It's generally good Python style to begin properties and attributes with a lower-case letter.
You shouldn't iterate over a query directly. This fetches results in batches, and is much less efficient than doing an explicit fetch. Instead, fetch the number of results you need with .fetch(n).
A try/except with no exception class specified and no action taken when an exception occurs is a very bad idea, and can mask a wide variety of issues.
Edit: I didn't notice that you were using an Expando - in which case #Daniel's answer is correct. There doesn't seem to be any good reason to use Expando here, though. Adding the property to the model (and updating existing entities) would be the easiest solution here.

Categories