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_todos
to add a total of 3 sample todos. Put your cursor ontodos.append(Todo('First'))
and pressCtrl-D
twice to duplicate the line. Changed the next two lines to have an argument of'Second'
and'Third'
. (macOS:Cmd-D
)The
Todo
class constructor looks weird.self.title
should be assigned on the first line. Click anywhere in that line and pressShift-Alt-Up
to 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_id
is probably better underlist
. With your cursor anywhere inget_id
, pressCmd-W
until PyCharm’s selection extends to including the method and the@staticmethod
decorator. (macOS:Alt-Up
)Press
Shift-Alt-Down
until the method moves afterlist
.As usual, press
Ctrl-Alt-L
to 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 = T
then tab,.
and tab to acceptget_id
, thent
and tab to completetodo_id
. UseShift-Enter
to 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-Enter
and 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.py
should match the following: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.py
should match the following: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-Up
andShift-Alt-Down
are 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-Up
to 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-Down
gradually de-select?
- Previous topic: List Todos Method
- Next topic: Debugging