I am currently producing a stock management system. All of the code so far works, however i have a variable which asks a user to input an ingredient name. If the ingredient name if found within the "inventory" table of the database i have created, then the record will be displayed to the user. Within each record, there are the fields: Ingredient, stock_level, Price, and Retailer. I'm not sure how to output the whole record to the user.
I have tried using the print(fetchone()), however if an ingredient is held in the database, "None" is outputted instead of the actual record
def searchIngredient():
found=0
while found == 0:
ingredient = input("Enter an ingredient name: ")
if len(ingredient) < 3:
print("Ingredient name must be three or more characters long")
continue
with sqlite3.connect("Inventory.db") as db:
cursor = db.cursor()
findIngredient = ("SELECT * FROM Inventory WHERE Ingredient=?")
cursor.execute(findIngredient, [(ingredient)])
if cursor.fetchall():
print(fetchone())
else:
found = 0
print("Ingredient does not exist in Inventory")
tryAgain = input("Do you want to enter another Retailer? Y or N ")
if tryAgain.lower() == "n":
mainMenu()
time.sleep(2)
mainMenu()
When run with the rest of the code, the user is asked to input an ingredient name (the format check works if string is less than three characters). With the fetchone() function, "None" is outputted when an ingredient name what exists in the db is entered. If the ingredient does not exist, the code works also. It is just the case of outputting the record to the user.
You are not fetching the record, instead:
# returns a list
for rec in cursor.fetchall():
# do something
# or
while True:
rec = cursor.fetchone()
if not rec:
break
# do something
Since fetch all the records can cause a very large list, it is recommended to loop over the records until you met None - no more to read. Look into the doc for more information.
Also Python has a standard lib logging. You don't have to print.
Example:
logger = logging.getLogger("SQL query")
logger.setLevel(logging.DEBUG)
logger.info("QUERY: %s" % query)
You can save it to a file:
hdlr = logging.FileHandler('query.log')
logger.addHandler(hdlr)
See the cookbook for more examples.
Related
Im making a simple form in python that inserts, deletes, updates and searches records. I want my code to check if a record exists against cnic number entered by user, if not then return a value or True/False. Any idea on what i could use?
This is my code.
def DeleteRecord():
cursor = conn.cursor()
cnic = cnicEntery.get()
validation = re.search(r"^[0-9+]{5}-[0-9+]{7}-[0-9]{1}$",cnic)
exists=Dlookup("cnic","Student","Criteria=cnic")
if cnic=='':
message.config(text="Enter CNIC# first!",foreground="red")
elif validation == None:
message.config(text="Invalid CNIC! Enter another!",foreground="red")
elif exists=='':
message.config("No record found to delete! Please try again!")
else:
cursor.execute('DELETE FROM Student WHERE cnic = ?', (cnic))
conn.commit()
message.config(text="Record has been deleted successfully!", foreground="green")
I tried using Dlookup but it did not work.
You don't really need to test for the existence of the row ahead of time. Just try to do the delete and then check .rowcount to see if any rows were actually deleted:
crsr.execute("DELETE FROM Student WHERE cnic = ?", cnic)
if crsr.rowcount:
print("Row deleted.")
else:
print("Row not found.")
I have this code
log_in = f'SELECT user_name,fname FROM users;'
cursor = connection.cursor()
cursor.execute(log_in)
result = cursor.fetchall()
cursor.close()
print(type(result))
print(result)
print('bfuqua' in result)
if 'bfuqua' in result:
unique = False
print('That user name already exists. Please try again.')
When I print the type I get <class 'list'> as the return type, [('bfuqua',)] as the data from the result variable. My problem is that it should be entering into the if statement but the return from the third print statement says False. It comes back as True when I put result[0], but I need to be able to scan the whole list for the string. I don't know what is going on.
If there are any other ways I can check to see if the string is in the return from the query, I am more than open to hear it!
Well if you would like to use your code you can iterate over result to achieve what you want:
for i in result:
if 'bfuqua' in i:
unique = False
print('That user name already exists. Please try again.')
But if you want to do it in a way suggested by #iuvbio I'd do it like:
def check_if_user_exists(username):
#by using "with" you dont need to worry about closing the connection
with connection.cursor() as cursor:
log_in = "SELECT user_name, fname FROM users WHERE user_name = %s"
cursor.execute(log_in, (username,))
result = cursor.fetchall()
# If there is no user, the result will be a tuple with 0 length
if len(result) == 0:
print("No user named {}".format(username))
# So here you can create user
else:
print("User {} already exists".format(username))
# Here you can create a notification for a client that the username already exists
check_if_user_exists("bfuqua")
I'm also a beginner so dont treat it like the one and only good solution but it works for me. Hope I was able to help :)
I am working on a project and in that, I've to work on sql. In the code, I've to work on a single row to match the values of a person.
def userid():
os.system('cls')
ii = input("enter your User ID: ")
curs.execute("SELECT ID FROM users") #shows ID row of users table
rows = curs.fetchall() #fetch all data of ID row
if (ii,) in rows: #if value of ii is in the row, condition evaluates
password()
else:
exit()
def password():
ps = getpass.getpass("enter your pin: ")
curs.execute("SELECT pin FROM users") #shows PIN row of users table
row = curs.fetchall() #fetch all data of pin row
if (ps,) in row: #if data in row matches with data in ps, condition evaluates
main()
else:
exit()
this is the code and you can see, in the first function, I am successful in fetching user ID but when it comes to passwords, I want to match the password in the row containing the UserId entered by the user. But instead, all passwords it contains is getting matched and error is occurring.
recently I discovered a keyword fetchone() but am not sure how to use it or it would work or not.
Please help me, how can I work on only one row in sql using python.
You need to use WHERE clauses to filter the query results before the database returns them. For example
SELECT ID, PIN FROM users WHERE ID = 42
will return only the id and pin for the user with id 42, or nothing if there is no row with this id.
Using WHERE clauses, we can change your code like this:
def userid():
os.system('cls')
ii = input("enter your User ID: ")
# I'm guessing ID is an integer value in the database?
id_ = int(ii)
# fetch matching id
curs.execute("SELECT ID FROM users WHERE ID = %s", (id_,))
row = curs.fetchone() #fetch all data of ID row
if row: # if the query returned a row, the id exists
password(id_)
else:
exit()
def password(id_):
ps = getpass.getpass("enter your pin: ")
# Fetch the PIN only for our user's ID
curs.execute("SELECT pin FROM users WHERE ID = %s", (id_,))
row = curs.fetchone() #fetch all data of pin row
# if data in row matches with data in ps, condition evaluates
if (ps,) in row:
main()
else:
exit()
Note that when checking credentials like this, it's common to get the id and password and check them both in a single query:
id_ = int(input('What is your id number?'))
password = getpass.getpass('What is your PIN?')
cur.execute("""SELECT id, password FROM users WHERE id = %s AND password = %s""",
(id_, password))
This is more efficient, because only one query is sent to the database, and potentially more secure, because if it fails the users does not know whether the id or password is wrong.
I'm creating a dictionary of two lists created by importing a csv file. Each of the two lists contain multiple lists of dictionaries with 8 key:value pairs per item. Each dictionary contains information about one particular item. One of the lists is information about multiple books; the other is information about multiple movies.
I need to query through the list of books by allowing a user to enter a query string which will be used to search against multiple fields in the list of books. The search needs to perform partial string matching and be case insensitive. All details for all matching books should be displayed without repeating any entries.
How do I search through a list and print the entire dictionary if it matches the query string?
# Note to self: book_collection is a list
# ORDER OF INFO in book_collection: title, author, publisher, pages, year, copies, available, ID
def query_book_collection(book_collection):
# check to see if the string is in the dictionary--partial string matching and case insensitive
query_string = input("Enter a query string to use for the search: ")
if query_string.lower() in book_collection:
print(book_collection)
else:
print("Sorry, that search returned no results.")
With the way I have it coded now, I expected it to match only full, direct matches (not partial string matches) and then print the full book_collection; however, it only ever prints "Sorry, that search returned no results."
EDIT: I have updated query_string.lower to query_string.lower().
The dictionary of books has 22 lists, and each list is a dictionary, I believe. One list (from the debugger) looks like this, for example:
: {'Title': 'My Best Book Ever', 'Author': 'Joseph Caldwell', 'Publisher': 'FPG Publishing', 'Pages': '317', 'Year': '2014', 'Copies': 3, 'Available': 3, 'ID': 17001}
The goal is to be able to search for any phrase, and if that phrase appears in the dictionary above, the entire dictionary will be printed.
Here is more of the code to give a bigger context, for those asking. The code I shared originally is just below the long print menu:
# each subset of the collection.
def load_collections():
# Load the two collections.
book_collection, max_book_id = load_collection("books.csv")
movie_collection, max_movie_id = load_collection("movies.csv")
# Check for error.
if book_collection is None or movie_collection is None:
return None, None
# Return the composite dictionary.
return {"books": book_collection, "movies": movie_collection}, max(max_book_id, max_movie_id)
# Loads a single collection and returns the data as a list. Upon error, None is returned.
def load_collection(file_name):
max_id = -1
try:
# Create an empty collection.
collection = []
# Open the file and read the field names
collection_file = open(file_name, "r")
field_names = collection_file.readline().rstrip().split(",")
# Read the remaining lines, splitting on commas, and creating dictionaries (one for each item)
for item in collection_file:
field_values = item.rstrip().split(",")
collection_item = {}
for index in range(len(field_values)):
if (field_names[index] == "Available") or (field_names[index] == "Copies") or (field_names[index] == "ID"):
collection_item[field_names[index]] = int(field_values[index])
else:
collection_item[field_names[index]] = field_values[index]
# Add the full item to the collection.
collection.append(collection_item)
# Update the max ID value
max_id = max(max_id, collection_item["ID"])
# Close the file now that we are done reading all of the lines.
collection_file.close()
# Catch IO Errors, with the File Not Found error the primary possible problem to detect.
except FileNotFoundError:
print("File not found when attempting to read", file_name)
return None
except IOError:
print("Error in data file when reading", file_name)
return None
# Return the collection.
return collection, max_id
# Display the menu of commands and get user's selection. Returns a string with the user's requested command.
# No validation is performed.
def prompt_user_with_menu():
print("\n\n********** Welcome to the Collection Manager. **********")
print("COMMAND FUNCTION")
print(" ci Check in an item")
print(" co Check out an item")
print(" ab Add a new book")
print(" am Add a new movie")
print(" db Display books")
print(" dm Display movies")
print(" qb Query for books")
print(" qm Query for movies")
print(" x Exit")
return input("Please enter a command to proceed: ")
# Create the query function. Prompts user to enter query string for a book and
# displays ALL results--partial string matching and case insensitive. Note to self: book_collection is a list
# ORDER OF INFO in book_collection: title, author, publisher, pages, year, copies, available, ID
def query_book_collection(book_collection):
# check to see if the string is in the dictionary--partial string matching and case insensitive
query_string = input("Enter a query string to use for the search: ")
if query_string.lower() in book_collection:
print(book_collection)
else:
print("Sorry, that search returned no results.")
def query_movie_collection():
pass
def check_out():
pass
def check_in():
pass
def get_item_ID():
pass
def display_collection():
pass
def add_book():
pass
def add_movie():
pass
# This is the main program function. It runs the main loop which prompts the user and performs the requested actions.
def main():
# Load the collections, and check for an error.
library_collections, max_existing_id = load_collections()
if library_collections is None:
print("The collections could not be loaded. Exiting.")
return
print("The collections have loaded successfully.")
# Display the error and get the operation code entered by the user. We perform this continuously until the
# user enters "x" to exit the program. Calls the appropriate function that corresponds to the requested operation.
operation = prompt_user_with_menu()
while operation != "x":
if operation == "ci":
check_in(library_collections)
elif operation == "co":
check_out(library_collections)
elif operation == "ab":
max_existing_id = add_book(library_collections["books"], max_existing_id)
elif operation == "am":
max_existing_id = add_movie(library_collections["movies"], max_existing_id)
elif operation == "db":
display_collection(library_collections["books"])
elif operation == "dm":
display_collection(library_collections["movies"])
elif operation == "qb":
query_book_collection(library_collections["books"])
elif operation == "qm":
query_movie_collection(library_collections["movies"])
else:
print("Unknown command. Please try again.")
operation = prompt_user_with_menu()
# Start the program.
main()
To match sub-strings you need to check each value of each book separately. This can be done with a loop and list comprehension:
found = False
for book in book_collection:
if any([query_string.lower() in str(val).lower() for val in book.values()]):
print(book_collection)
found == True
if not found:
print("Sorry, that search returned no results.")
The str(val) is required as some data in book_collection is not a string.
You could join all values in collection together before use in opearator:
def query_book_collection(book_collection):
query_string = input("Enter a query string to use for the search: ")
collection_string = ",".join(map(str, book_collection.values())).lower()
if query_string.lower() in collection_string:
print(book_collection)
else:
print("Sorry, that search returned no results.")
but the more efficient way should be adding a new property which concat all the values for querying into book_collection when you load your collection in your load_collection function. like(using python buildin csv module to read csv file):
def load_collection(file_name):
try:
with open(file_name, "r") as f:
reader = csv.DictReader(f)
collection = []
max_id = -1
for item in reader:
# add a field for querying
item["_fulltext"] = ",".join(item.values())
# casting type
item["Available"] = int(item["Available"])
item["Copies"] = int(item["Copies"])
item["ID"] = int(item["ID"])
collection.append(item)
max_id = max(max_id, item["ID"])
return collection, max_id
except FileNotFoundError:
print("File not found when attempting to read", file_name)
return None, None
except IOError:
print("Error in data file when reading", file_name)
return None, None
then, you query function would be like:
def query_book_collection(book_collection):
query_string = input("Enter a query string to use for the search: ")
if query_string.lower() in book_collection["_fulltext"]:
print(book_collection)
else:
print("Sorry, that search returned no results.")
I need to assign a unique name that contains the word 'user' and a certain random numbers to a user. Something like user32944, user80890 etc. So I write a program something like this
import random
user_list = ["user32944", "user60690"] # essentially this list is what I retrieve from some database
user_name = ""
while(True):
if user_name not in user_list:
user_name = "user" + str(random.random() * 100000).split(".")[0]
break
print(user_name)
But if I deliberately set the user_name to something that already exists in the list, my program doesn't exit the loop and the program hangs.
What am I doing wrong?
You only perform a action when the generated username is not in the list, but you don't do anything when the username is in the list. And therefore you don't exit the while loop and the program will hang.
The following code sample does what you want. Although i recommend you to explore the uuid package in python.
import random
user_list = ["user32944", "user60690"] # essentially this list is what I retrieve from some database
def generateRandomUsername():
randomNr = random.randint(1,3)
if randomNr == 1:
return "user32944"
else:
return "user" + str(random.random() * 100000).split(".")[0]
def getRandomUniqueUsername():
while(True):
username = generateRandomUsername()
if username not in user_list:
print('Created user \'%s\'' % username)
return username
else:
print("Username \'%s\'already exists, generating new one" % username)
def printUsernameList():
for username in user_list:
print('Username: %s' % username)
#Create 4 random usernames
for i in range(4):
username = getRandomUniqueUsername()
user_list.append(username)
print('Printing user_list...')
printUsernameList()
That will never exit the loop because you are never satisfying the IF condition and there is no conditional expression on while too, you gave True in while condition -> which means it loops infinitely.
So if you do not satsifying the IF condition then write a logic what you would want to do incase IF does not get statisified and then break out of the loop.
And if you want guid with just random alphanumeric ids, then use uuid package in python.