Welcome to the Treehouse Community
Want to collaborate on code errors? Have bugs you need feedback on? Looking for an extra set of eyes on your latest project? Get support with fellow developers, designers, and programmers of all backgrounds and skill levels here with the Treehouse Community! While you're at it, check out some resources Treehouse students have shared here.
Looking to learn something new?
Treehouse offers a seven day free trial for new students. Get access to thousands of hours of content and join thousands of Treehouse students and alumni in the community today.
Start your free trial
David Dzsotjan
6,405 PointsTo-do list app in Python
Inspired by the diary app in the Databases in Python course of Kenneth Love, I've made a to-do list app. It lets you add and delete entries, modify them, as well as flag them 'DONE'. There is a handy cleanup feature that gets rid of all completed (DONE) entries that are more than a week old, unless they are flagged 'Protected'. Please feel free to make suggestions and comments!:)
"""To-do list where you can chronologically add your tasks, modify them and mark if they have been completed.
A cleanup feature enables you to delete completed tasks which are more than a week old - unless
you have flagged them as 'protected'."""
from collections import OrderedDict
import datetime
import os
from peewee import *
db = SqliteDatabase('to_do_list.db')
class ToDo(Model):
"""Model for creating to-do items. 'done' indicates that it's been completed,
'protected' makes it immune to cleanup"""
task = CharField(max_length=255)
timestamp = DateTimeField(default=datetime.datetime.now)
done = BooleanField(default=False)
protected = BooleanField(default=False)
class Meta:
database = db
def clear():
"""Clear the display"""
os.system('cls' if os.name == 'nt' else 'clear')
def initialize():
"""Connect to database, build tables if they don't exist"""
db.connect()
db.create_tables([ToDo], safe=True)
def view_entries(index, entries, single_entry):
""""View to-do list"""
clear()
index = index % len(entries) # determines which entry is selected for modification
if single_entry: # to see only 1 entry
entries = [entries[index]]
index = 0
else:
print('\nMY TO-DO LIST')
print('=' * 40)
prev_timestamp = None
for ind, entry in enumerate(entries):
timestamp = entry.timestamp.strftime('%d/%B/%Y')
if timestamp != prev_timestamp: # same timestamps get printed only once
print('\n')
print(timestamp)
print('=' * len(timestamp))
prev_timestamp = timestamp
if ind == index: # placing the selection tick
tick = '> '
else:
tick = ' '
print('{}{}'.format(tick, entry.task), end='')
if entry.done:
print('\t(DONE)', end='')
if entry.protected:
print('\t <P>', end='')
print('')
return entries # so that we can modify the given entry if needed
def add_entry(index, entries):
"""Add a new task"""
new_task = input('\nTo do: ')
if input('Protect [yN]? ').lower().strip() == 'y':
protect = True
else:
protect = False
ToDo.create(task=new_task,
protected=protect)
def modify_entry(index, entries):
"""Modify selected entry"""
entry = view_entries(index, entries, True)[0]
print('\n\n')
for key, value in sub_menu.items():
print('{}) {}'.format(key, sub_menu[key].__doc__))
print('q) Back to Main')
next_action = input('Action: ')
if next_action.lower().strip() in sub_menu:
sub_menu[next_action](entry)
else:
return
def cleanup_entries(index, entries):
"""Cleanup: delete completed, non-protected entries older than a week"""
if (input('Have you checked that you protected the important stuff? [yN]').lower().strip() == 'y'):
now = datetime.datetime.now()
for entry in entries:
if (now - entry.timestamp > datetime.timedelta(7, 0, 0) and entry.done and not entry.protected):
entry.delete_instance()
def modify_task(entry):
"""Modify task"""
new_task = input('> ')
entry.task = new_task
entry.save()
def delete_entry(entry):
"""Erase entry"""
if (input('Are you sure [yN]? ').lower().strip() == 'y'):
entry.delete_instance()
def toggle_done(entry):
"""Toggle 'DONE'"""
entry.done = not entry.done
entry.save()
def toggle_protection(entry):
"""Toggle 'protected'"""
entry.protected = not entry.protected
entry.save()
def menu_loop():
choice = None
index = 0 # shows which entry is selected
entries = ToDo.select().order_by(ToDo.timestamp.asc())
while choice != 'q':
if len(entries) != 0:
view_entries(index, entries, False)
print('\n' + '=' * 40 + '\n')
print('Previous/Next: p/n \n')
for key, value in main_menu.items():
print('{}) {}'.format(key, value.__doc__))
print('q) Quit')
choice = input('\nAction: ')
if choice in main_menu:
try:
main_menu[choice](index, entries)
except ZeroDivisionError:
continue
entries = ToDo.select().order_by(ToDo.timestamp.asc()) # update entries after operations
elif choice == 'n':
index += 1
elif choice == 'p':
index -= 1
main_menu = OrderedDict([
('a', add_entry),
('m', modify_entry),
('c', cleanup_entries)
])
sub_menu = OrderedDict([
('m', modify_task),
('d', toggle_done),
('p', toggle_protection),
('e', delete_entry)
])
if __name__ == '__main__':
initialize()
menu_loop()
db.close()
1 Answer
Alex Anarcho
9,910 Pointsvery cool, trying to do the same thing. already created a program that takes links i found interesting on the web and stores them. you can tag by keyword and search for keywords to find links quickly.
one problem i have encountered, let me know how you solved it: when running the program from the terminal (another directory) i have to specify the absolute filepath. is there any solution to not hardcore said path to locate the db?