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
ToDoinstead 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
eintitle, pressAlt-Enter.Choose
Add field 'title' to class ToDofrom 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-Enterto 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-Leftto jump by word. (macOS:Alt-Left)As always,
Ctrl-Alt-Lto 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_todosto append instances:todos.append(ToDo('First')).Change the
printstatement at the bottom toprint(todos).Re-run to confirm, using
Shift-F10. (macOS:Ctrl-R)Our
app.pyneeds to get itstodosfrommodels.pyinstead of keeping its own list.Remove the
todosassignment line fromapp.py.Add an import, after the first import:
from models import todos
Remember to use autocomplete on models and todos
list_todosis 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-Enterand choosing the first choice. Then add().Now reload your browser and you should see your list of one todo.
Your
app.pyshould match the following:app.py in Todo Class¶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.pyshould match the following:models.py in Todo Class¶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