How to do it...
Have a look at the following layout:
flask_app/ - run.py my_app/ - __init__.py - product/ - __init__.py - views.py - models.py - templates/ - base.html - home.html - product.html - static/ - js/ - bootstrap.min.js - css/ - bootstrap.min.css - main.css
In the preceding layout, static/css/bootstrap.min.css and static/js/bootstrap.min.js are standard files that can be downloaded from the Bootstrap website mentioned in the Getting ready section. The run.py file remains the same, as always. The rest of the application building process is as follows:
First, define the models in my_app/product/models.py. In this chapter, we will work on a simple, non-persistent key-value store. We will start with a few hardcoded product records made well in advance, as follows:
PRODUCTS = { 'iphone': { 'name': 'iPhone 5S', 'category': 'Phones', 'price': 699, }, 'galaxy': { 'name': 'Samsung Galaxy 5', 'category': 'Phones', 'price': 649, }, 'ipad-air': { 'name': 'iPad Air', 'category': 'Tablets', 'price': 649, }, 'ipad-mini': { 'name': 'iPad Mini', 'category': 'Tablets', 'price': 549 } }
Next comes the views, that is, my_app/product/views.py. Here, we will follow the blueprint style to write the application, as follows:
from werkzeug import abort from flask import render_template from flask import Blueprint from my_app.product.models import PRODUCTS product_blueprint = Blueprint('product', __name__) @product_blueprint.route('/') @product_blueprint.route('/home') def home(): return render_template('home.html', products=PRODUCTS) @product_blueprint.route('/product/<key>') def product(key): product = PRODUCTS.get(key) if not product: abort(404) return render_template('product.html', product=product)
The name of the blueprint (product) that is passed in the Blueprint constructor will be appended to the endpoints defined in this blueprint. Have a look at the base.html code for clarity.
Now, create the application's configuration file, my_app/__init__.py, which should look like the following lines of code:
from flask import Flask from my_app.product.views import product_blueprint app = Flask(__name__) app.register_blueprint(product_blueprint)
As well as the CSS code provided by Bootstrap, add a bit of custom CSS code in my_app/static/css/main.css, as follows:
body { padding-top: 50px; } .top-pad { padding: 40px 15px; text-align: center; }
When considering templates, remember that the first template acts as the base for all templates. Name this template base.html and place it in my_app/templates/base.html, as follows:
<!DOCTYPE html> <html lang="en"> <head> <meta charset="utf-8"> <meta http-equiv="X-UA-Compatible" content="IE=edge"> <meta name="viewport" content="width=device-width, initial-
scale=1"> <title>Flask Framework Cookbook</title> <link href="{{ url_for('static',
filename='css/bootstrap.min.css') }}" rel="stylesheet"> <link href="{{ url_for('static', filename='css/main.css') }}"
rel="stylesheet"> </head> <body> <div class="navbar navbar-inverse navbar-fixed-top"
role="navigation"> <div class="container"> <div class="navbar-header"> <a class="navbar-brand" href="{{ url_for('product.home')
}}">Flask Cookbook</a> </div> </div> </div> <div class="container"> {% block container %}{% endblock %} </div> <!-- jQuery (necessary for Bootstrap's JavaScript plugins) --> <script src="https://ajax.googleapis.com/ajax/libs/jquery/
2.0.0/jquery.min.js"></script> <script src="{{ url_for('static', filename='js/
bootstrap.min.js') }}"></script> </body> </html>
Most of the preceding code contains normal HTML and Jinja2 evaluation placeholders, which we introduced in the previous chapter. An important point to note, however, is how the url_for() method is used for blueprint URLs. The blueprint name is appended to all endpoints. This becomes very useful when there are multiple blueprints inside one application, as some of them may have similar looking URLs.
On the home page, my_app/templates/home.html, iterate over all the products and display them, as follows:
{% extends 'base.html' %} {% block container %} <div class="top-pad"> {% for id, product in products.items() %} <div class="well"> <h2> <a href="{{ url_for('product.product', key=id) }}">{{
product['name'] }}</a> <small>$ {{ product['price'] }}</small> </h2> </div> {% endfor %} </div> {% endblock %}
Then, create the individual product page, my_app/templates/product.html, which should look like the following lines of code:
{% extends 'home.html' %} {% block container %} <div class="top-pad"> <h1>{{ product['name'] }} <small>{{ product['category'] }}</small> </h1> <h3>$ {{ product['price'] }}</h3> </div> {% endblock %}