Single Todo¶
Our show_todo is still using dummy data. Let’s have it use actual data,
with a lookup static method from models.Todo similar to how we get the
list of todos. As we do this, we’ll see how to efficiently re-arrange code.
Steps¶
In
models.py, let’s start by extendingpopulate_todosto add a total of 3 sample todos. Put your cursor ontodos.append(Todo('First'))and pressCtrl-Dtwice to duplicate the line. Changed the next two lines to have an argument of'Second'and'Third'. (macOS:Cmd-D)The
Todoclass constructor looks weird.self.titleshould be assigned on the first line. Click anywhere in that line and pressShift-Alt-Upto move the line up.After the
__init__constructor, add a new method:def get_id(self, todo_id): return [todo for todo in todos if todo.id == todo_id][0]
Hmm, PyCharm thinks something’s going on with
get_id. Mouse-over it and see that it thinks this method can be static. Click ondef get_id, pressAlt-Enter, and change it to a static method.Let’s take this for a test drive. Change
model.py‘s main block:if __name__ == '__main__': populate_todos() first_todo = Todo.list()[0] first_id = first_todo.id print(Todo.get_id(first_id))
Re-run
models.py(make sure the correct run configuration is selected.)We realize
get_idis probably better underlist. With your cursor anywhere inget_id, pressCmd-Wuntil PyCharm’s selection extends to including the method and the@staticmethoddecorator. (macOS:Alt-Up)Press
Shift-Alt-Downuntil the method moves afterlist.As usual, press
Ctrl-Alt-Lto clean up any line formatting. (macOS:Cmd-Alt-L)We need our web app to use this method for
show_todo. Let’s add a first line inshow_todo:todo = Todo.get_id(todo_id)
using autocomplete. Type
todo = Tthen tab,.and tab to acceptget_id, thentand tab to completetodo_id. UseShift-Enterto make a second line.Let’s have a bit richer HTML. On the second line in
show_todo, define a format stringfmt = ''.With your cursor inside that string, press
Alt-Enterand chooseInject language reference -> HTML. Now provide this for the value:fmt = '<h1>Todo {todo_id}</h1><p>{title}</p>'
As you type, you’ll get the full power of WebStorm HTML editing, right in your Python string.
Change the third line to use this format string:
return fmt.format(todo_id=todo.id, title=todo.title)
Reload your browser and go to a todo. You’ll get an error in
get_id. Later we’ll use the debugger to hunt down the problem. The reason is, the route gives us a string and our id’s are integers. Change the route definition to@app.route('/todo/<int:todo_id>').Reload your browser.
Your
app.pyshould match the following:app.py in Single Todo¶from flask import Flask from models import populate_todos, Todo app = Flask(__name__) @app.route('/') def home_page(): return 'Hello World! <a href="/todo/">Todos</a>' @app.route('/todo/') def list_todos(): todos = Todo.list() 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/<int:todo_id>') def show_todo(todo_id): todo = Todo.get_id(todo_id) fmt = '<h1>Todo {todo_id}</h1><p>{title}</p>' return fmt.format(todo_id=todo.id, title=todo.title) if __name__ == '__main__': populate_todos() app.run(debug=True)
Your
models.pyshould match the following:models.py in Single Todo¶from random import randint todos = [] class Todo: def __init__(self, title): self.title = title self.display_fmt = 'Todo {todo_id}' self.id = randint(1000, 9999) def __repr__(self): return self.display @property def display(self): return self.display_fmt.format(todo_id=self.id) @staticmethod def list(): return todos @staticmethod def get_id(todo_id): return [todo for todo in todos if todo.id == todo_id][0] def populate_todos(): todos.append(Todo('First')) todos.append(Todo('Second')) todos.append(Todo('Third')) if __name__ == '__main__': populate_todos() first_todo = Todo.list()[0] first_id = first_todo.id print(Todo.get_id(first_id))
Analysis¶
PyCharm’s productivity features are starting to show:
- Moving lines.
Shift-Alt-UpandShift-Alt-Downare so much faster then cutting and pasting the line. You don’t even have to select anything, just click in the line. - Smart autocomplete. In many places, we get accurate and fast completion.
- Language injection. Having HTML-aware editing, in the middle of Python, is quite useful. Same is true for CSS, SQL, JS, etc.
Extra Credit¶
- We also use
Shift-Alt-Upto move a line up. Can we select an entire method and move it, usingShift-Alt-Up? - If we extend our selection too far with
Ctrl-W(macOS:Alt-Up), willAlt-Downgradually de-select?
- Previous topic: List Todos Method
- Next topic: Debugging