We’ve now created an index page with all of our items, and also individual pages for each item. We will need to do some formatting on these template pages to make sure they look right and make sense, and I will also need to find out how to make sure that the purchased checkbox (if that’s what I do) has the correct functionality, but I’m reasonably placed with the current work – which will be adding the option to create, update and delete (as we’ve already added the ability to read).
8. Creating items
8.1 Creating a New Item
To get this started, we’re going to edit the app.py file. To make it so that people can add new items, we need to be able to make requests, so we will use the request object from Flask. We will also import url_for(), flash() and redirect(). The import section should look like this:
import sqlite3
from flask import Flask, render_template, request, url_for, flash, redirect
from werkzeug.exceptions import abort
The flash function stores flashed messages in the client’s browser session. This requires getting a secret key. This is used to secure sessions. To se this, we do the following:
app = Flask(__name__)
app.config[‘SECRET_KEY’] = ‘your secret key’
@app.route(‘/’)
def index():
conn = get_db_connection()
posts = conn.execute(‘SELECT * FROM items’).fetchall()
conn.close()
return render_template(‘index.html’, items=items)
Now we need to create a view function that will render a template that displays a form you can fill in to create a new item. In the app.py file:
@app.route(‘/create’, methods=(‘GET’, ‘POST’))
def create():
return render_template(‘create.html’)
This create a /create route that accepts both GET and POST requests. Now let’s create a template called create.html.
{% extends ‘base.html’ %}
{% block content %}
<h1>{% block title %} Create a New Item {% endblock %}</h1>
<form method=”post”>
<div class=”form-group”>
<label for=”title”>Title</label>
<input type=”text” name=“item”
placeholder=“item” class=”form-control”
value=”{{ request.form[‘item’] }}”></input>
</div>
<div class=”form-group”>
<label for=”content”>Content</label>
<textarea name=”content” placeholder=“item description”
class=”form-control”>{{ request.form[‘description’] }}</textarea>
</div>
<div class=”form-group”>
<button type=”submit” class=”btn btn-primary”>Submit</button>
</div>
</form>
{% endblock %}
Now we can go back and edit the create() view function:
@app.route(‘/create’, methods=(‘GET’, ‘POST’))
def create():
if request.method == ‘POST’:
item = request.form[‘item’]
description = request.form[‘description’]
if not title:
flash(‘Item is required!’)
else:
conn = get_db_connection()
conn.execute(‘INSERT INTO items (item, description) VALUES (?, ?)’,
(item, description))
conn.commit()
conn.close()
return redirect(url_for(‘index’))
return render_template(‘create.html’)
Our final step is to add a new <li> tag following the About link inside the <nav> tag. Inside base.html
<nav class=”navbar navbar-expand-md navbar-light bg-light”>
<a class=”navbar-brand” href=”{{ url_for(‘index’)}}”>FlaskBlog</a>
<button class=”navbar-toggler” type=”button” data-toggle=”collapse” data-target=”#navbarNav” aria-controls=”navbarNav” aria-expanded=”false” aria-label=”Toggle navigation”>
<span class=”navbar-toggler-icon”></span>
</button>
<div class=”collapse navbar-collapse” id=”navbarNav”>
<ul class=”navbar-nav”>
<li class=”nav-item”>
<a class=”nav-link” href=”#”>About</a>
</li>
<li class=”nav-item”>
<a class=”nav-link” href=”{{url_for(‘create’)}}”>New Post</a>
</li>
</ul>
</div>
</nav>
<div class=”container”>
{% for message in get_flashed_messages() %}
<div class=”alert alert-danger”>{{ message }}</div>
{% endfor %}
{% block content %} {% endblock %}
</div>