Part 2: Adding Features
Last updated
Last updated
Now that we have a working development environment and have become familiar with running our todo
app, we can build in our initial feature set to manage task items.
Before we can create anything, we need some way to store it. For this project, we've chosen , a light-weight key-value database that stores data on disk in a single JSON file.
Let's begin by adding the dependency to our requirements.txt
file, and installing it to our virtualenv:
Add the following to the bottom of the pip requirements.txt
file:
Install the new requirements with pip
:
With our dependency installed, we need to add it to our application. The primary things we will cover here are:
Configuration settings for where we will store the db.json
file on disk
Using framework hooks to run code at a specific point in our runtime
Extending our app
with a db
object we will use to integrate and access the TinyDB functionality in our application
Find and modify the following section of todo/main.py
in order to define a default configuration for our database file called db_file
:
To be kind to our users, we will also want to add this default setting to our example configuration file config/todo.yml.example
. Modify the file to include the following:
Add the following to the top of the todo/main.py
file:
We've created a function to extend our application to include an app.db
object, however in order for it to take affect we need to register the function as a hook with the framework. Add the following hooks
meta option to our Todo app in todo/main.py
:
Now, when we run todo
again you will see that our hook is executed (via the info
logs):
And we can see that the database was created:
In order to work with todo items we need to map out commands with our app. We could do this with the existing Base
controller, however to keep code clean and organized we want to create an new controller called Items
.
Add the following stubs to todo/controllers/items.py
as a placeholder for our sub-commands:
We've created the controller code, however for it to take affect we need to register it with our application.
Add/modify the following in todo/main.py
:
With our new controller registered, lets see it in action:
We've stubbed out our Items
controller and sub-commands, so lets add the actual code that will support each of these features:
Add/modify the following in todo/controllers/items.py
:
We've now built out the functionality to create items in our database, that will include the text
, a state
(pending/complete), and also the timestamp
of when it was created/updated. Notice that we've added arguments to the sub-command function, and not the controller because the item_text
argument is only relevant to the create
action, and not the application or controller namespace as a whole.
Let's try it out:
We've created an item, so now we need to be able to list them. First, let's take a look at our database:
We can see that TinyDB automatically generates database IDs, so we will want to display that when listing our items so that we can easily update/delete/complete by ID later.
Add/modify the following in todo/controllers/items.py
:
It's a little messy, but that's why we put this in a separate template and not in our code. We are including the ID so that we can use that for updating/deleting/etc, and also a [ ]
(checkbox) that will be "checked" when the item's state is complete
.
Let's have a go:
If we've made a typo, or want to change an existing item we need a way to update it.
Add/modify the following in todo/controllers/items.py
:
Given a TinyDB ID, we can update our item including touching the timestamp
and modifying the text. Let's update our todo item:
A TODO list is not complete (ah! pun intended) without the ability to check off items that are done. This operation gets a little more interesting as we want to also send an email message when items are completed.
Add/modify the following in todo/controllers/items.py
:
Add/modify the following in todo/main.py
:
Now let's complete one of our items:
Finally, if we just want to get rid of something, we need the ability to delete it:
Add/modify the following in todo/controllers/items.py
:
And lets delete our completed item:
That concludes Part 2! We now have a fully functional TODO application. In the next parts we will discuss more indepth about extending the project with plugins, and digging deeper on things like documentation and testing.
We want to extend our application with a re-usable db
object that can be used throughout our code. There are many ways we could do this, however here we are going to use a .
At this point, we have a decision to make regarding . Do we want our controllers commands to appear embedded under the primary applications namespace (ex: todo my-command
) or do we want a separate nested namespace (ex: todo items my-command
). As our application is still small, we will opt to embed our controllers commands under the primary namespace (to keep our commands and examples shorter).
Here we are pulling all of the items from the database, putting it into a data dictionary, then rendering with the . Put the following in the template file todo/templates/items/list.jinja2
: