---
# System prepended metadata

title: ftw flask

---

---
title: ftw flask
tag: ftw
---
# Flask Intro

* [Slides](https://www.beautiful.ai/player/-Li6qtReuVH3XY66--OU)

### Toolshed

* [Flask Official Site](http://flask.pocoo.org/)
* [Flask SQLAlchemy Quickstart](http://flask-sqlalchemy.pocoo.org/2.3/quickstart/#a-minimal-application)

### Library

#### Background
* [History of MVC](https://hackernoon.com/from-mvc-to-modern-web-frameworks-8067ec9dee65)
* [Flask vs Django, why Flask is better](https://www.codementor.io/garethdwyer/flask-vs-django-why-flask-might-be-better-4xs7mdf8v)
* [Which should I learn, Flask or Django?](https://blog.tecladocode.com/learn-python-flask-or-django/)
* [Flask or Django? An In Depth Comparison](https://scotch.io/bar-talk/flask-or-django-an-in-depth-comparison-part-one#toc-popularity)
* [Flask vs Django](https://www.netguru.com/blog/flask-vs-django-comparison-which-python-framework-is-better-for-your-app)

#### Flask
* [The Definitive Flask Tutorial](https://blog.miguelgrinberg.com/post/the-flask-mega-tutorial-part-i-hello-world) - our stuff borrows a few parts from this tutorial. It's probably the most well-known Flask tutorial on the web, and has a lot of good content. 
* [Flask Tutorial](https://realpython.com/introduction-to-flask-part-1-setting-up-a-static-site/) - watch out, it's in Python 2.7.
* [Flask Resources](https://www.fullstackpython.com/flask.html) - a long list of resources about Flask.
* [Official Flask Tutorial](http://flask.pocoo.org/docs/1.0/tutorial/) - a bit confusing as they're using Blueprints, which we won't cover just yet. 
* [Official Flask Tutorial, but rewritten unofficially into SQLAlchemy](https://github.com/brennv/flaskr-sqlalchemy)

#### Other Topics
* [Flask Templates](http://flask.pocoo.org/docs/1.0/tutorial/templates/) - worth reading through this section, for sure.
* [Python Decorators](https://realpython.com/primer-on-python-decorators/) - if you want to know how the `@route` decorators work, they basically just wrap the function inside another function. 
* [SQLAlchemy Resources](https://www.fullstackpython.com/sqlalchemy.html)
* [Flask Receiving Data](https://scotch.io/bar-talk/processing-incoming-request-data-in-flask)


## Exercise

We're going to build a small blog-like application. 

### Milestone 1: Get Started

Create a new application, and create a new file. You can call it whatever you like; why not `blog.py`?

Create your main routes. For now, it's okay to have everything in one file as our app will stay simple. 

The routes you'll need are:

* The default base route. This should return a redirect to `/posts`. 
    *[Flask Documentation on how to Redirect](http://flask.pocoo.org/docs/1.0/quickstart/#redirects-and-errors) 
* A `/posts` route to show all the posts.
* A `/create` route that shows a form to create a new post. 

### Milestone 2: Create your Models

For this application, we'll keep things simple and not have a real user authentication system; we only need one table for now. 

Define your model for `Post`. It should have a few fields:
* id (always)
* title
* body
* author_name
* created_at
* updated_at

Those last two models, you'll be able to use a nice feature of SQLAlchemy: https://stackoverflow.com/a/12155686/396324. As you use SQLALchemy more and more, you'll start to like it more. 

Remember to make the title and body required, and have some minimum length. A great way to do this in SQLAlchemy is to use the [@validates decorator](https://stackoverflow.com/a/18579864/396324). 

You do the above _in addition_ to defining `NOT NULL`, as in the [simple example from the docs](https://flask-sqlalchemy.readthedocs.io/en/stable/models/#simple-example). `nullable=False` enforces this at the database level - `@validates` works at the Python level.

### Milestone 3: Create your first form

The most common framework is Flask-WTF, but we'll learn that later. What's nice about Flask is we can build simple solutions first. 

We'll just use `request.form`. There's an article linked above in the resources that has a longer introduction, but for now the code sample [at the official docs](http://flask.pocoo.org/docs/1.0/quickstart/#the-request-object) should have everything you need.

First though let's create the actual form. Create a new route, called `/create`, that renders a template for a form (something like `render_template('create_form.html'`).

After you have created your form, let's write the more interesting part: the handler.

At the top of your code, make sure to import:
```
from flask import request
```

We can actually process the creation into the same handler that displays the form - we can use `GET` and `POST` to differentiate between showing the form or processing the form. It's common practice to do this, but you can definitely create different endpoints if you wish.

```
@app.route('/create', methods=['POST', 'GET'])
def login():
    error = None
    if request.method == 'POST':
        # access the data using request.form['field_name']
        # save it to the database
        # return a redirect to /posts
    # the code below is executed if the request method
    # was GET or the credentials were invalid
    return render_template('create_form.html')
```

### Milestone 4: Add Bootstrap and some Styling

To do this, we'll have to use template inheritance. Your pages probably don't have a nice head, body, and consistent style, nav bar, footer, that sort of stuff that you're probably used to. 

[Flask Documentation](http://flask.pocoo.org/docs/1.0/patterns/templateinheritance/) is great here. 

Two steps:
1. Create a file called `layout.html`, with named "blocks" for the children to fill in.
2. Child templates all call `{% extends "layout.html" %}`. 

### Milestone 5: Flash Messages / Error Feedback

We redirect to posts right away when we create a new post, whether it was successful or not. 

Two things to change:

1. Only redirect to `/posts` if the model creation was successful. Else, redirect back to `/create`.
2. Show a `flash` message explaining what happened.

[http://flask.pocoo.org/docs/1.0/patterns/flashing/](Flask documentation) is great here again. On the backend side, all you have to do is create a line that says something like `flash('Post created')`. 

If there was an error, just call `flash('Error during model creation')`. 
