Flask is a great Python web framework. It's very small, simple, and, best of all, it's easy to learn.
Today I will take you to build your first flask Web App! As with the official tutorials, you will build your own micro-blogging system: Flaskr. Unlike the official Flask tutorial, we use Stormpath to create and manage user accounts and data, and you're more productive. The development process will be significantly faster!
Let's get started.
Note: This tutorial is for flask developers to help them understand how to build a simple website using flask and Stormpath. This is the revision of the official Flask tutorial.
Goal
The goal of the FLASKR application is simple:
- Allows users to log in and out of the micro-blogging system with pre-generated accounts (saved with Stormpath).
- Allow logged-in users to add entries containing plain text and some HTML body text on the page. The user is considered trustworthy and the HTML content is not reviewed.
- Show all blog entries in chronological order (new on top) on the website home page.
The final website should look like this:
Get ready
Before we start, we need to install some Python packs before we can work! We pass? Python Package Manager pip to complete this thing.
Pip Install flask Flask-stormpath
The above command installs two packages: Flask, and Flask-stormpath, both of which will be used throughout the tutorial.
Next, you need to create a Stormpath account. You can register at Stormpath website: https://api.stormpath.com/register
Once you have created a Stormpath account and logged in, you will also need to create an API key. You can do this by clicking the Create API Key button on the action page: Https://api.stormpath.com/ui/dashboard
Once you have created the API key, you will be prompted to download a file named Apikey.properties, which we will use later.
Note: Do not check the Apikey.properties file into your version control system (if you are using it)! This file stores your Stormpath certificate and should be properly kept.
Next, you will want to create a new Stormpath app, visit the Apps page: Https://api.stormpath.com/v#!applications?, click Register App. Create a new app named Flaskr, with the options by default.
Finally, visit the Account page: Https://api.stormpath.com/ui/accounts/create? , create a new user account in Flaskr directory. All the accounts created here can be used to log in to the micro blog you will be building.
Directory structure
The first thing you need to do is create a directory structure that holds your app's code. You need to create several directories and then put your apikey.properites in the new project directory:
$ mkdir-p Flaskr/{static,templates}; CP ~/path/to/apikey.properties flaskr/$ Tree flaskrflaskr├──apikey.properties├──static└──templates 2 directories, 1 fi Le
The Flaskr directory will be your app's root directory. The static directory is used to store your static files (css,javascript, and image files). The templates directory is used to store your Jinja templates (for rendering HTML).
Install the App
Now that your directory structure is set up, we are ready to configure the app!
First, create a new file named flaskr.py in your Flaskr directory. Your application code is placed in this file.
Everything will start here:
From datetime import datetime from flask import (flask, abort, Flash, redirect, render_template, request, Url_for,) from F Lask.ext.stormpath Import (Stormpatherror, Stormpathmanager, User, login_required, Login_user, logout_user, user,) app = Flask (__name__) app.config[' DEBUG ' = trueapp.config[' secret_key '] = ' some_really_long_random_string_here ' app. config[' stormpath_api_key_file ' = ' apikey.properties ' app.config[' stormpath_application '] = ' flaskr ' stormpath_ Manager = Stormpathmanager (APP) If __name__ = = ' __main__ ': App.run ()
What to look for:
- At the beginning of the flaskr.py file you have imported several libraries-the entire tutorial below will use them
- You've created an App object--This is the core of every flask project
- You have added several configuration variables in app. Config. App. Config is a python dictionary variable that you can use to store any custom configuration you want to store. Here we set a number of important variables that will be used later:
- The DEBUG variable can be set to TRUE or false. It is used to control the built-in error reporting behavior of flask (it allows flask to display detailed error messages in development mode)
- The Secret_key variable is used internally to ensure client session security. When deploying a real flask application, make sure that this is a long, randomly generated string.
- Stormpath_api_key_file? The variable should point to your apikey.properties file location. For more information see: http://flask-stormpath.readthedocs.org/en/latest/setup.html
- The stormpath_application variable should be the name of the Stormpath app you created earlier.
- You create a Stormpath_manager object that controls the Stormpath library, which will help you easily interact with users and user data.
- You ' re Calling?app.run ()? At the bottom. This tells Flask-to-run your site in development mode for testing.
- At the end you call the App.run ()?. It tells Flask to run your site in development mode for easy testing.
After running the following command, you can see that your flask app is starting to run on port 5000:
$ python flaskr.py * Running on Http://127.0.0.1:5000/* Restarting with Reloader
But when you visit http://127.0.0.1:5000, you will see a 404 Not Found information. This is because you have not defined any views or URL routes.
View
Now that you have finished installing the parts, let's define the view. The following code should be placed in the flaskr.py file, above:
if __name__ = = ' __main__ ': App.run ()
The code is as follows:
@app. Route ('/') def show_posts (): posts = [] for account in Stormpath_manager.application.accounts:if Account.custom_dat A.get (' posts '): Posts.extend (account.custom_data[' posts ']) posts = sorted (posts, Key=lambda k:k[' Date '), reverse=true Return render_template (' show_posts.html ', posts=posts) @app. Route ('/add ', methods=[' POST ') @login_requireddef add_ Post (): If not user.custom_data.get (' posts '): user.custom_data[' posts '] = [] user.custom_data[' posts '].append ({' Date ') : Datetime.utcnow (). Isoformat (), ' title ': request.form[' title '], ' text ': request.form[' text '],}) User.save () Flash (' N EW post successfully added. ') Return Redirect (Url_for (' show_posts ')) @app. Route ('/login ', methods=[' GET ', ' POST ') def login (): Error = None if request . method = = ' POST ': try: _user = user.from_login (request.form[' email '), request.form[' password '], login_use R (_user, remember=true) Flash (' You were logged in. ') return redirect (Url_for (' show_posts ')) except Stormpatherror, E Rr: Error = Err.message return render_template (' login.html ', Error=error) @app. Route ('/logout ') def logout (): Logout_user () Flash (' You were logged out. ') Return Redirect (Url_for (' show_posts '))
Let's discuss the above code.
You may notice that the function defined first is show_posts. This function is used to display posted posts on the front page of the site. As you might have guessed, the adorner @app.route ('/') tells Flask how to run the function.
Each time the user requests the URL "/", Flask runs show_posts and returns the output to the user.
Show_posts is just:
- Iterate through all user accounts and find posts. Each blog post is a simple Python dictionary in the following format:
{' Date ': ' 2014-04-01t22:50:49.762475 ', ' text ': ' Blog content ', ' title ': ' Post title '}
- Each blog post is added to the posts array.
- Sorts the posts array by date, so the new publication is in front.
- An HTML template called show_posts.html is rendered with an posts array as input.
- The add_posts view is used to log in users to publish post to the site. This view brings a few things like this:
- The adorner @app.route ('/add ', methods=[' post ') tells Flask that the URL only accepts POST requests. Flask accepts only get requests by default.
- @login_required adorner ensures that the user has logged in before accessing the view. If the user tries to post to the view without logging in, an HTTP 401 is not authorized to answer.
- Any decorations? @login_required view can access the user variable. This is an object that holds the details of the user account.
Its working mechanism is simple:
- Check if there are any saved posts under the user's account. This step is achieved by checking that user.custom_data.get (' posts ') is not false. User.custom_data is a python dictionary where you can save any user data you want to save.
- Grab the title and body from the POST request and create a new post object in the user's posts array.
- Save the post to the Stormpath of the user account.
- Issue a message that will be displayed to the user later.
- Finally, redirect the user to the Show_posts view so that the newly added blog post can be displayed.
- The login and logout views are particularly simple.
The login view simply extracts the e-mail address and password from the user post request, crawls the user object from Stormpath, attempts to log on, and creates a local session.
The logout view is the destruction of the user session.
Template
The next thing to add is the template code. Flask uses the Jinja template language, which makes it very easy to write HTML templates.
Let's define a layout template templates/layout.html as the start. The other templates we write later will come from this base template. This strategy is useful because it allows you to define template code that will be referenced multiple times in one place.
Add the following code to your layout.html template file:
Flaskr
Flaskr
{% if User.email%} log out {% Else%} log in {% endif%} {% to message in get_flashed_messages ()%} {{message}} {%} ENDfor%} {% block body%}{% endblock%}
Next is the templates/show_posts.html template file:
{% extends "layout.html"%} {% block body%} {% if User.email%} {% ENDIF%}
{% for post in posts%}
{{post[' title '}}
- Unbelievable. No posts here so far!
{% Endblock%}
Finally, the templates/login.html template file:
Login
{% if error%}Error: {{Error}} {% ENDIF%} {% Endblock%}
The first thing to note is? The layout.html template defines a body block that can be substituted by a block of the same name in any child template.
The layout.html template displays a login or logout template and also displays all the flashback information.
{% if User.email%}
Because you're using Flask-stormpath, all templates have access to a magical user variable. When a user is logged in, all the details of the user are visible (so this check will take effect).
Show_posts.html? The template iterates over the posts array, which is passed in when Render_template is called by the show_posts view. Jinja allows you to use a for loop for anything that can be iterated.
It is also important that, in order to output variable content, you need to add curly braces outside the variable.
{{variable}} {{post[' text ']|safe}}
Now that we've decided to allow users to enter wayward HTML code in their blog post, we have to use the template's safe filter to output the body block in the blog post.
Jinja automatically ignores any special characters by default, so we have to use safe filters to display user-entered HTML and JavaScript.
Add Style
The last thing to do is to create a static/style.css file with the following content:
Body {font-family:sans-serif; background: #eee;} A, H1, H2 {color: #377ba8;} H1, H2 {font-family: ' Georgia ', serif; margin:0;} H1 {border-bottom:2px solid #eee;} H2 {font-size:1.2em;}. page {margin:2em auto; width:35em; border:5px solid #ccc; Padding:0.8em; Background:white; }.entries {list-style:none; margin:0; padding:0;}. Entries Li {margin:0.8em 1.2em;}. Entries Li H2 {margin-left: -1em;}. Add-entry {font-size:0.9em; border-bottom:1px solid #ccc;}. Add-entry dl {font-weight:bold;}. Metanav {text-align:right; font-size:0.8em; padding:0.3em; Margin-bottom:1em; Background: #fafafa; }.flash {background: #cee5F5; padding:0.5em; border:1px solid #aacbe2; }.error {background: #f0d6d6; padding:0.5em;}
This file will be loaded by the layout.html template, providing a decent display style.
Test it
Now that we've finished coding the app, let's take a look at the final product!
In order to run your cool new website, you must first restart the Flask Web server with the following command:
$ python flaskr.py * Running on Http://127.0.0.1:5000/* Restarting with Reloader
Then visit http://127.0.0.1:5000 in your browser. You should now be able to see the running Flaskr website and be able to log in with your Stormpath account, post a blog, and so on.