Welcome!
This is the community forum for my apps Pythonista and Editorial.
For individual support questions, you can also send an email. If you have a very short question or just want to say hello — I'm @olemoritz on Twitter.
Button that will cycle through SQLite records
-
Hello,
My first post so if I miss something in proper edict let me know as well. I am just starting out in using Pythonista.
I am trying to make an attendance app. I want a Ui to pop up and it will have a date field, meeting description field, last name, first name, and two buttons that will say Here and Not here.
I am pulling from a SQLite database. I have two tables, one a members table that stores the names and an attendance table that will store the meeting date and who attended. I am able to pull a list from the table and get the first name displayed in my Ui.
What is suppose to happen is when I press Here or Not Here, the names displayed on the UI should go to the next name on the imported list. But It doesn’t seem to display the next one. I am at a loss where to fix. I have been trying all different ways but have failed.
UPDATE:
I figured out the loop and where to have it run within the button function. Below is the entire script. I hope it will help others.Here is my code so far:
import ui import sqlite3 attendanceView = ui.View('attendance_UI.pyui') conn = sqlite3.connect('fire_department.db') cur = conn.cursor() cur.execute('SELECT id,last_name,first_name FROM members ORDER BY last_name ASC') members_list = cur.fetchall() list_config = 0 s_listConfig = str(list_config) #member = members_list[list_config] #member_id = member[0] #lastName = member[1] #firstName = member[2] #@ui.in_background def button_here(sender): lastName = sender.superview['lastnameEntry'] firstName = sender.superview['firstnameEntry'] count = sender.superview['listCount'] buttonLabel = sender.superview['hereButton'] member = members_list[int(count.text)] lastName.text = member[1] firstName.text = member[2] new_count = int(count.text) + 1 count.text = str(new_count) buttonLabel.title = 'Here' def button_notHere(sender): lastName = sender.superview['lastnameEntry'] firstName = sender.superview['firstnameEntry'] count = sender.superview['listCount'] buttonLabel = sender.superview['hereButton'] member = members_list[int(count.text)] lastName.text = member[1] firstName.text = member[2] new_count = int(count.text) + 1 count.text = str(new_count) v = ui.load_view('attendance_UI') v['listCount'].text = s_listConfig #v['lastnameEntry'].text = lastName #v['firstnameEntry'].text = firstName v.present('sheet')
Any help in tweaking this to make it cycle through would be greatly appreciated.
-
@groesch16, here’s as short as possible, but runnable as-is, example of how I would do this without extra counters, using a simple generator expression (
get_member
).I have left out last name, ”Not here” and db handling for brevity.
import console import ui # Data members = ( ('First', 'Last'), ('Another', 'Second'), ) get_member = (member for member in members) present_members = 0 # UI elements firstname_label = ui.Label( text_color='white', height=50, flex='W', ) here_button = ui.Button( title="Here", y=50, height=50, flex='W', tint_color='white', background_color='grey', ) # Logic def show_next_member(): member = next(get_member, None) if member: first, last = member firstname_label.text = first else: console.alert('All members shown') show_next_member() # First name shown at start def count_here(sender): global present_members present_members += 1 sender.title = f'Here - {present_members}' show_next_member() here_button.action = count_here root = ui.View() root.add_subview(firstname_label) root.add_subview(here_button) root.present('fullscreen')
-
Thank you! That is definitely much cleaner
-
@groesch16, for your use case, a TableView could also be convenient. It supports multiple selection, so you could just scroll through the list and make selections (and correct mistakes), then press save.
-
I’m working on a table view right now but I can’t pull the text value from row 1. I can’t find any examples and the documentation is super vague.
I created a table that is to break up the meeting type. It lists:
Dept Meeting
Fire Call
Ems callI want to select one of these and it will take the text value and write it to SQL. But I can’t figure out the attribute structure or the correct command to get it.
Here is what I have:
import ui import sqlite3 attendanceView = ui.View('attendance_UI.pyui') list_config = 0 s_listConfig = str(list_config) def button_here(sender): lastName = sender.superview['lastnameEntry'] firstName = sender.superview['firstnameEntry'] count = sender.superview['listCount'] buttonLabel = sender.superview['hereButton'] meeting_date = sender.superview['datefield'] meeting_type = sender.superview['meetingtypeEntry'] if count == 0: new_count = int(count.text) + 1 count.text = str(new_count) else: conn = sqlite3.connect('fire_department.db') cur = conn.cursor() cur.execute('SELECT id,last_name,first_name,status FROM members ORDER BY status,last_name;') members_list = cur.fetchall() member = members_list[int(count.text)] cur.execute("INSERT INTO attendance(attendance_type,present,date,members_id) Values ('{}','{}','{}','{}')".format(meeting_type.text,'Here',meeting_date.text,str(member[0]))); conn.commit() lastName.text = member[1] firstName.text = member[2] new_count = int(count.text) + 1 count.text = str(new_count) buttonLabel.title = 'Here' def button_notHere(sender): lastName = sender.superview['lastnameEntry'] firstName = sender.superview['firstnameEntry'] count = sender.superview['listCount'] buttonLabel = sender.superview['hereButton'] meeting_date = sender.superview['datefield'] meeting_type = sender.superview['meetingtypeEntry'] meeting_select = sender.superview['attendanceTable'] # This is where i am trying to pull from the table view of the meeting type meeting_select = ui.TableView() meeting_select = meeting_select.selected_row if count == 0: new_count = int(count.text) + 1 count.text = str(new_count) else: conn = sqlite3.connect('fire_department.db') cur = conn.cursor() cur.execute('SELECT id,last_name,first_name,status FROM members ORDER BY status,last_name;') members_list = cur.fetchall() member = members_list[int(count.text)] cur.execute("INSERT INTO attendance(attendance_type,present,date,members_id) Values ('{}','{}','{}','{}')".format(meeting_select.text,'Not Here',meeting_date.text,str(member[0]))); conn.commit() lastName.text = member[1] firstName.text = member[2] new_count = int(count.text) + 1 count.text = str(new_count) v = ui.load_view('attendance_UI') v['listCount'].text = s_listConfig v.present('sheet')
The def button_notHere is where I am trying to pull the table data. Once I get the not here button to work then I would put it into the here as well. The name i tide to the table in the Ui editor is attendanceTable.
-
If you are just trying to people the user for a choice, consider using
dialogs
. List_dialog might be what you need. -
@groesch16, just to clarify my understanding before offering advice:
You have 3 types of situations where you need a roll call. Does the group of people who could be present differ, or is it always the same?
-
The people in the roll call will always be the same.
My end goal is to try make it easy to take attendance and have it upload to the database. The first script that I updated does it where I manually write it in to a text field.
Now I am trying to improve it where it’s even easier. If I can just select the meeting type it would make filling out the form even quicker. There are more than 3 types of situations but if I can get it with 3 then I can do it with the rest.
-
@JonB How would I use dialogs?
I am still new at all of this. But I will start researching that suggestion.
-
You can look at some examples of dialogs and tableview here.
https://github.com/encela95dus/ios_pythonista_examples -
@groesch16, my suggestion would be to have meeting type selection at the top, then a tableview with all names. You select those present, and click Save to save selected names to the database (and if you like, unselected names as ”not here”).
If that sounds useful, I can do a quick demo for you.
-
Please send me a demo. That would work for the EMS call and the Fire call type. When a Fire/EMS call should happen it would be easier to select the names of the people who showed up to the call. It might even prove a better way then what I am trying to do.
The way I have it setup, I was envisioning it as when the secretary is doing roll call in the meeting, the secretary can just press the here or not here button as this person is reading out the names.
-
@groesch16 Are you on GitHub? https://github.com/search?q=groesch&type=users
-
I am. It’s the same name as this one. I am just starting my journey as a developer. I only have one 1 public repository right now. I am trying to grow and make more.
-
@groesch16, here’s a quick demo with meeting type selector at top and then a list of names to choose from:
import ui meeting_types = ('EMS', 'Fire') # Names loaded from db members = ( ('First', 'Last'), ('Another', 'Second'), ) class Members(ui.ListDataSource): def __init__(self, members): super().__init__(members) self.members = members def tableview_cell_for_row(self, tableview, section, row): cell = ui.TableViewCell() first, last = self.members[row] cell.text_label.text = f"{last}, {first}" return cell # UI elements root = ui.View(name="Roll Call") meeting_selector = ui.SegmentedControl( segments=meeting_types, selected_index=0, frame=(0, 0, 100, 40), flex='W', background_color='grey', ) table = ui.TableView( allows_multiple_selection=True, frame=(0, 40, 100, 60), flex='WH', ) table.data_source = Members(members) save_button = ui.ButtonItem(title='Save') root.right_button_items = [save_button] # Process results def save_names_to_db(sender): selected_meeting_type = meeting_types[meeting_selector.selected_index] selected_names = [members[row] for _, row in table.selected_rows] # Save selected_names to db here print(f"Meeting: {selected_meeting_type}") print(f"Present: {selected_names}") save_button.action = save_names_to_db root.add_subview(meeting_selector) root.add_subview(table) root.present('fullscreen')
-
Wow! This concept is great! This definitely seems like a way better solution then what I was doing. I am going to mess around with this and I will update it with what I got to see how far I have gotten.
Thanks for this!!