Todo Class¶
We’re going to start a Todo
class, to replace each dictionary in our
todos` list. We’ll let PyCharm help us with this code refactoring,
including changing our app.py
web app to use model.todos
.
Steps¶
Near the top, under
todos = []
, let’s define a class. Type the following and stop at that point:class ToDo: def in
...and hit
tab
. PyCharm will complete the__init__(self):
.Note
Yes, we said
ToDo
instead ofTodo
. We will come back to clean that up later.Left-arrow back into the constructor, after self, and change it to
(self, title):
.With the cursor still on the
e
intitle
, pressAlt-Enter
.Choose
Add field 'title' to class ToDo
from the Quick Fix list.With the red box outlining
.title
, press enter to accept the suggested field name and jump to the end of the line.On the next line in the constructor, add
self.id = randint(1000, 9999)
and, when your cursor is after the last9
, pressShift-Enter
to Start New Line after the end of the current line.Note: By generating random ids, every restart will provide new URLs when going to the show_todo URL. Keep this in mind. You will have to go back to the ``list_todos`` URL, reload, and click a link.
Click in
randint
, pressAlt-Enter
, and chooseImport 'random.randint'
. To move there from the end of the line, you can useCtrl-Left
to jump by word. (macOS:Alt-Left
)As always,
Ctrl-Alt-L
to clean up formatting. (macOS:Cmd-Alt-L
)Make a Python representation by starting a new method:
def rep
...and hit
tab
. PyCharm will complete the__repr__(self):
.Finish the method with
return 'Todo {todo_id}'.format(todo_id=self.id)
.Change
populate_todos
to append instances:todos.append(ToDo('First'))
.Change the
print
statement at the bottom toprint(todos)
.Re-run to confirm, using
Shift-F10
. (macOS:Ctrl-R
)Our
app.py
needs to get itstodos
frommodels.py
instead of keeping its own list.Remove the
todos
assignment line fromapp.py
.Add an import, after the first import:
from models import todos
Remember to use autocomplete on models and todos
list_todos
is using dictionary access. Let’s convert it to attribute access:items = [div.format(id=t.id, title=t.title) for t in todos]
Remember to use autocomplete on ``.format``!
Finally, we need to populate our todos. In the main block at the bottom for
app.py
, start a new line and typepopulate_todos
.Before adding parentheses, generate the import by pressing
Alt-Enter
and choosing the first choice. Then add()
.Now reload your browser and you should see your list of one todo.
Your
app.py
should match the following:from flask import Flask from models import todos, populate_todos app = Flask(__name__) @app.route('/') def home_page(): return 'Hello World! <a href="/todo/">Todos</a>' @app.route('/todo/') def list_todos(): div = '<div><a href="/todo/{id}">{title}</a></div>' items = [div.format(id=t.id, title=t.title) for t in todos] return '\n'.join(items) @app.route('/todo/<todo_id>') def show_todo(todo_id): return 'Todo {todo_id}'.format(todo_id=todo_id) if __name__ == '__main__': populate_todos() app.run(debug=True)
Your
models.py
should match the following:from random import randint todos = [] class ToDo: def __init__(self, title): self.title = title self.id = randint(1000, 9999) def __repr__(self): return 'Todo {todo_id}'.format(todo_id=self.id) def populate_todos(): todos.append(ToDo('First')) if __name__ == '__main__': populate_todos() print(todos)
Analysis¶
We did quite a lot in this step, letting PyCharm help us on productivity.
- Autocomplete. PyCharm handled a lot of typing for us on
__init__
and__repr__
, as well as.format
. Even if it isn’t a lot of characters, it’s better to let PyCharm do the completion, to avoid typos and add in the parens, self, etc. - Refactoring. The “Add field ‘title’ to class ToDo” refactoring was quite helpful. This happens in constructors and methods often.
- Generate imports. It’s nice to let PyCharm generate the import just by using a symbol. Not only does it generate the import, but it leaves your cursor exactly where you left it.
Extra Credit¶
- If you have to stop your editing and go somewhere to add/fix a line, what is a quick way to jump back to where you were at?
- Does PyCharm have a Code Intention to convert dictionary access
(
todo['id']
) to attribute access (todo.id
)?
- Previous topic: Todo Dicts
- Next topic: List Todos Method