Using Flask-Login for User Management with Flask


The following is a guest post by Jeff Knupp, author of Writing Idiomatic Python. Jeff currently has a Kickstarter campaign running to turn the book into a video series - check it out!

A few months ago, I grew tired of the digital goods payment service I used to sell my book and decided to write my own. Two hours later, bull was born. It was a little application written using Flask and Python, which turned out to be an excellent choice for implementation. It started with bare bones functionality: A customer could enter their details in a Stripe JavaScript pop-up, bull would record their email address and create a unique id for the purchase, then associate the user with the content they purchased.

It worked fantastically well. Whereas before a potential customer had to not only, enter their full name and address (both of which I had no use for), they also had to create an account on my payment processor's site. I'm not sure how many sales I lost due to the convoluted checkout process, but I'm sure it was a good deal. With bull, the time between clicking the "Buy Now" button on the book sales page to actually reading the book was about 10 seconds. Customers loved it.

I loved it too, but for a slightly different reason: since bull was running on my web server, I could get a much richer set of analytics than if I had to send customers to a third-party site for payment. This opened the door to a host of new possibilities: A/B testing, analytics reports, custom sales reports. I was stoked.

Adding Users

I decided that, at a minimum, I wanted bull to be able to display a "Sales Overview" page that contained basic sales data: transaction information, graphs of sales over time, etc. To do that (in a secure manner), I needed to add authentication and authorization to my little Flask app. Helpfully, though, I only needed to support a single, "admin" user who was authorized to view reports.

Luckily, as is usually the case, a third-party package already existed to handle this. Flask-login is a Flask extension that enables user authentication. All that's required is a User model and a few simple functions. Let's take a look at what was required.

The User Model

bull was already using Flask-sqlalchemy to create purchase and product models which captured the information about a sale and a product, respectively. Flask-login requires a User model with the following properties:

Primer on Jinja Templating



Right out of the box, Flask includes the powerful Jinja templating language. It's modeled after Django templates (but it renders much faster) and, although, Flask does not force you to use any templating language, it assumes that you'll be using Jinja since it does come pre-installed.

For those who have not been exposed to a templating language before, such languages essentially contain variables as well as some programming logic, which when evaluated (or rendered into HTML) are replaced with actual values. The variables and/or logic are placed between tags or delimiters. For example, Jinja templates use {% ... %} for expressions or logic (like for loops), while {{ ... }} are used for outputting the results of an expression or a variable to the end user. The latter tag, when rendered, is replaced with a value or values, and are seen by the end user.

Jinja Templates are just .html files. By convention they live in the "/templates" directory in a Flask project. If you're familiar with string formatting or interpolation, templating languages follow a similiar type of logic - just on the scale of an entire HTML page.

Quick Examples

Make sure you have Jinja installed before running these examples - pip install jinja2

>>> from jinja2 import Template
>>> t = Template("Hello {{ something }}!")
>>> t.render(something="World")
u'Hello World!'
>>> t = Template("My favorite numbers: {% for n in range(1,10) %}{{n}} " "{% endfor %}")
>>> t.render()
u'My favorite numbers: 1 2 3 4 5 6 7 8 9 '

Primer on Python Decorators


Decorators provide a simple syntax for calling higher-order functions. By definition, a decorator is a function that takes another function and extends the behavior of the latter function without explicitly modifying it. Sounds confusing - but it's really not, especially after we go over a number of examples.

In this introductory tutorial, we'll look at what decorators are and how to create and use them.

You can find all the examples from this article here.

Before you can understand decorators, you must first understand:

  1. How functions work. Essentially, functions return a value based on the given arguments.

    def foo(bar):
      return bar + 1
    print foo(2) == 3
  2. In Python, functions are first-class objects. This means that functions can be passed around, and used as arguments, just like any other value (e.g, string, int, float).

    def foo(bar):
      return bar+1
    print foo
    print foo(2)
    print type(foo)
    def call_foo_with_arg(foo, arg):
      return foo(arg)
    print call_foo_with_arg(foo, 3)
  3. Because of the first-class nature of functions in Python, you can define functions inside other functions. Such functions are called nested functions.

    def parent():
      print "Printing from the parent() function."
      def first_child():
          return "Printing from the first_child() function."
      def second_child():
          return "Printing from the second_child() function."
      print first_child()
      print second_child()

    What happens when you call the parent() function? Think about this for a minute. You should get ...

    Printing from the parent() function.
    Printing from the first_child() function.
    Printing from the second_child() function

    Try calling the first_child(). You should get an error:

    Traceback (most recent call last):
    File "", line 15, in <module>
    NameError: name 'first_child' is not defined

    What have we learned?

    Whenever you call parent(), the sibling functions, first_child() and second_child() are also called AND because of scope, both of the sibling functions are not available (e.g., cannot be called) outside of the parent function.

  4. Python also allows you to return functions from other functions. Let's alter the previous function for this example.

    def parent(num):
      def first_child():
          return "Printing from the first_child() function."
      def second_child():
          return "Printing from the second_child() function."
          assert num == 10
          return first_child
      except AssertionError:
          return second_child
    foo = parent(10)
    bar = parent(11)
    print foo
    print bar
    print foo()
    print bar()

    The output of the first two print statements is:

    <function first_child at 0x1004a8c08>
    <function second_child at 0x1004a8cf8>

    This simply means that foo points to the first_child() function, while bar points to the second_child() function.

    The output of the second two functions confirms this:

    Printing from the first_child() function.
    Printing from the second_child() function.

    Finally, did you notice that in example three, we executed the sibling functions within the parent functions - e.g, second_child(). Meanwhile in this last example, we did not add parenthesis to the sibling functions - first_child - when called so that way we can use them in the future. Make sense?

Python Web Applications With Flask - Part III


Please note: This is a collaboration piece between Michael Herman, from Real Python, and Sean Vieira, a Python developer from De Deo Designs.

Articles in this series:

  1. Part I: Application setup
  2. Part II: Setup user accounts, Templates, Static files
  3. Part III: Testing (unit and integration), Debugging, and Error handling <-- *CURRENT ARTICLE*

Welcome back to the Flask-Tracking development series! For those of you who are just joining us, we are implementing a web analytics application that conforms to this napkin specification. For all those of you following along at home, you may check out today's code with-

$ git checkout v0.3

-or you may download it from the releases page on Github. Those of you who are just joining us may wish to read a note on the repository structure as well.

In the previous segment we added user accounts to our application. This week we'll work on implementing a testing framework, talk a bit about why testing is important and then write some tests for our application. After, we'll talk a bit about debugging errors in our application and logging.

Why Testing

Before we actually write any of our tests lets talk about why testing is important. If you remember the Zen of Python from Part 1, you may have noticed that "Simple is better than complex" is right above "Complex is better than complicated". Simple is the ideal, complex is often a reality. Web applications, in particular, have many moving parts, and can very quickly move from simple to complex.

Working with Django and Flask on Nitrous.IO


This is a guest post by our friend Greg McKeever from Nitrous.IO.

Nitrous.IO is a platform which allows you to spin up your own development environment quickly in the cloud. Here are a few key advantages of coding on Nitrous.IO:

  • Save countless hours (or days) of setting up your Windows or Mac OS for development. Your Nitrous box comes pre-loaded with many tools and interpreters, so you can start coding immediately.

  • Your code is accessible from any computer or mobile device. Edit code via Web IDE, SSH, or sync locally and use your favorite text editor.

  • Collaboration: Nitrous provides a way for you to share your development environment with any other user. If you are running into any issues with your project and need help, you can invite a friend to your Nitrous box to edit and run your code.

To get started, sign up at Nitrous.IO. Once your account is confirmed, navigate to the boxes page and create a new Python/Django box.

Create Python Box

There are many tools and interpreters which are included with the Nitrous box, and at the time of writing this you will have Python 2.7.3 and Django 1.5.1 included with your dev environment. If this is what you are wanting to start working with then everything is ready to go!

If you are looking to use a different version of Python, Django, or utilize another framework such as Flask, keep reading.

Setting up Python 2.7 with Virtualenv

Virtualenv allows you to create an isolated environment in order to install specific versions of Python, Django, and also install other frameworks such as Flask without requiring root access. Since the Nitrous boxes do not offer root at this time, this is the best route to go.

To view the available versions of Python available, run ls /usr/bin/python* in the console. Create a new environment with Python 2.7 by running the following command: