---
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')`.