Welcome to the Treehouse Community
Want to collaborate on code errors? Have bugs you need feedback on? Looking for an extra set of eyes on your latest project? Get support with fellow developers, designers, and programmers of all backgrounds and skill levels here with the Treehouse Community! While you're at it, check out some resources Treehouse students have shared here.
Looking to learn something new?
Treehouse offers a seven day free trial for new students. Get access to thousands of hours of content and join thousands of Treehouse students and alumni in the community today.
Start your free trialManish Giri
16,266 PointsUnderstanding the flow of 'setting the cookie'
I think I got lost halfway through the video. Things were fine until the get_saved_data() method was defined. After that, I just couldn't understand the flow of the whole process. It also doesn't help that the instructor doesn't explain the things he uses in the video BEFORE using them. It's of course very apparent to him because he knows this stuff, but for beginners to Flask, all this need not be so evident.
For instance - why was get_saved_data() called in the save() method? I mean I know it's so that you have the latest data, but why is that needed for this example? Then the update() method is called on data. What's the purpose of that? Again, I know that update() changes the value of a dict to update the values of the passed in dict, but why is that needed in this example? You're anyway always displaying the latest 'cookie' value right? You can't have multiple cookies show up in the form under the bear thing.
Also, there's the saves variable that pops out of nowhere. What's the need for that?
I tried to trace through the code with comments and put some ? marks on places I didn't grasp fully (including the above questions).
from flask import Flask
from flask import render_template, redirect, url_for, json, make_response, request
app = Flask(__name__)
def get_saved_data():
try:
#json.loads takes a JSON string and turns it into "Python object ???"
data = json.loads(request.cookies.get('character'))
except TypeError:
data = {}
return data
# route for homepage
@app.route('/')
def index():
# this view is called when the request comes in at homepage /
# get_saved_data() is called to look for any saved data, which in this case, is the cookie
data = get_saved_data()
# if nothing is saved, an empty dict is returned and stored in the saves variable
# in index.html, the value for the key 'name' (of cookie) is displayed - blank if nothing is set
return render_template("index.html", saves=data)
@app.route('/save', methods=['POST'])
def save():
"""
this method is called as the handler when user submits the form
method saves the user's input data to set a cookie
"""
response = make_response(redirect(url_for('index')))
# load existing saved data
data = get_saved_data()
# updates current dict with new values ???
data.update(dict(request.form.items()))
# sets value of cookie named 'character' to be value entered by user in form
response.set_cookie('character', json.dumps(dict(request.form.items())))
# return response to be displayed to user
return response
app.run(debug=True, host='0.0.0.0', port=8000)
Looking for some help!
1 Answer
Chris Freeman
Treehouse Moderator 68,457 PointsLet's start with review of some concepts.
When a browser requests a webpage, flask creates a request
object with:
- data from the URL query data (items after the "?" in the URL): stored in
request.args
- data from a submitted form: stored in
request.form
- data from previously set cookies: stored in
request.cookie
All cookie data received from the browser is found in request.cookie
. All cookie data sent to the browser is added as an attribute to the response
At the beginning there is no cookie data and request.cookie
is empty. Any cookie data, if present, is received from the browser on every request.
As a precaution, since we don't know ahead of time whether there are current cookies set in the browser (from some other page view, or other future added view code), it is best to merge any data for new cookies with current cookies received from the browser. Without this merge, we might accidentally clearing cookies we are unaware of by not sending them back to the browser.
A helper function get_saved_data()
is created to extract data from the cookies out of the current request. (A better name might be get_received_cookie_data()
). Cookie data is received as JSON string. The function json.loads
translates this string into a python dict.
In the index() view, get_saved_data()
is used to help populate the index.html
template with any cookie data if present.
In the save() view, the form data received from the browser will be sent back to the browser as a cookie. The first step is to use get_saved_data()
to get the current cookie data received from the browser and place it in the dict data
.
The data.update()
is a fancy way to update one dict with the contents of another. Otherwise, we would need to loop through the form data and add each key/value pair to the data
dict. At this point, data
has the merged values from current cookies and form data. The last task is getting the merged cookie data back to the browser.
Continuing in the save()
view, the response sent from the server will be a redirect
(HTTP status code 302) which will say to the browser: "Ask again for this page, but use URL 'index' instead". We piggy-back any cookie data we want to send on this response. The cookie data is prepared by converting data
into a string using json.dumps()
and added as an attribute using response.set_cookie
.
When the browser gets the "302" response with the piggy-backed cookie data, it saves the cookies, then resubmits a new request to '/index' including the latest (just saved) cookies.
Back in the index()
view, this new request received with the latest cookies is used to populate the 'index.html' template. The saves=data
part of the render_template
function, assigns the data
dict to the context variable 'saves'. This context variable is accessed in the 'index.html' template using {{ saves.get(....) }}
to extract values from the dictionary and display them in the template.
That's a lot of info. Let me know if you have more questions (or if I got something wrong).
Kourosh Raeen
23,733 PointsKourosh Raeen
23,733 PointsThis is a great explanation! Thank!
Jay Reyes
Python Web Development Techdegree Student 15,937 PointsJay Reyes
Python Web Development Techdegree Student 15,937 PointsA fundamental explanation, Chris.
One note here: " Continuing in the save() view, the response sent to the server will be a redirect (HTTP status code 302) which will say to the browser:"
Should that instead say, "Continuing in the save() view, the response sent to the browser"?
Chris Freeman
Treehouse Moderator 68,457 PointsChris Freeman
Treehouse Moderator 68,457 Points@Jay Reyes, Could catch! I've updated the text to read "Continuing in the save() view, the response sent from the server will be a redirect...."