4 minute read

In this post, we’re going to create a simple web app that allows users to input a message, as well as their name or handle, and allow users to view five random messages they’ve submitted. We’ll be using the flask library. To store the messages, we use a database file and use SQL queries to view the stored messages. Here’s a link to my project repository.

The get_message_db() Function

To initialize the table of messages in our database, we use the sqllite3 library and SQL. We check if the message_db database is in our app first, and once it’s connected, we create a messages table inside it to store our messages.

def get_message_db():
    # if message_db isn't in the g attribute of the app, connect it to the messages_db.sqlite database
    if "message_db" not in g:
        g.message_db = sqlite3.connect("messages_db.sqlite")

    cursor = g.message_db.cursor()

    # create messages table if it doesn't exist within message_db, with id, handle, and message
    cursor.execute("CREATE TABLE IF NOT EXISTS messages(id INT, handle TEXT, message TEXT)")

    return g.message_db

We’ll be using get_message_db() to access our messages table in the following functions.

The insert_message(request) Function

We use this function to insert messages and their handles in the messages table. The id for each message and handle is the number of rows in the messages table plus one.

def insert_message(request):
    # extract message from form in submit.html
    message = request.form["message"]

    # extract handle from form in submit.html
    handle = request.form["handle"]
    cursor = get_message_db().cursor()

    # count number of rows in messages table to create id for messages and handles
    cursor.execute("SELECT COUNT(*) FROM messages")
    number_of_rows = cursor.fetchone()

    # insert message and handle into messages table, making id one plus number of rows in message table
    cursor.execute("INSERT INTO messages(id, handle, message) VALUES(" + str(number_of_rows[0] + 1) + ", \"" + handle + "\", \"" + message + "\")")
    get_message_db().commit()
    get_message_db().close()

We’ll use this function once the request method from our submit.html becomes POST (e.g. when a user submits a message and handle).

The random_messages(n) Function

Again, we use SQL and extract n random messages to return.

def random_messages(n):
    cursor = get_message_db().cursor()

    # select random n rows from messages table
    cursor.execute("SELECT * FROM messages ORDER BY RANDOM() LIMIT " + str(n))

    # fetch n random messages and handles
    random_messages = cursor.fetchall()

    get_message_db().close()
    return random_messages

We pass random_messages(n) to our view.html file to display if the user has submitted messages.

The main() Function

The main() function renders base.html, the base page of our website.

@app.route("/")
def main():
    return render_template("base.html")

The submit() Function

The submit() function renders submit.html, which contains input fields for users to input their message and their handle. If the request method is POST, which occurs when a user has submitted a message and handle, the website will display a message thanking the user for their submission; otherwise the page displays two blank fields and a submit button.

@app.route("/submit/", methods = ["POST", "GET"])
def submit():
    # if no message and handle are submitted, display submit.html
    if request.method == "GET":
        return render_template("submit.html")

    else:
        # if message and handle are submitted, display submit.html with a thank you message
        try:
            insert_message(request)
            return render_template("submit.html", thanks = True)

        except:
            return render_template("submit.html")

The view() Function

The view() function renders view.html, which displays five randomly chosen messages.

@app.route("/view/")
def view():
    # Displays five random messages on view.html
    return render_template("view.html", random_messages = random_messages(5))

The base.html File

The base.html file displays the title and description of our site, as well as two links to submit a message and to view messages that were submitted.


<!doctype html>
<link rel="stylesheet" href="{{ url_for('static', filename='style.css') }}">
<!-- Title -->
<title>A Simple Message Bank</title>
<nav>
  <h1>A Simple Message Bank</h1>
  <!-- Description -->
  <h5>An unapologetically simple message bank. Submit a message, and click "View messages" to view five random messages you've submitted!</h5>
  <ul>
    <!-- Link to submit a message -->
    <li><a href="{{ url_for('submit') }}">Submit a message</a></li>
    <!-- Link to view messages -->
    <li><a href="{{ url_for('view') }}">View messages</a></li>
  </ul>
</nav>
<section class="content">
    <header>
      {% block header %}{% endblock %}
    </header>
    {% block content %}{% endblock %}
  </section>

The submit.html File

The submit.html file displays base.html, as well as two boxes to submit a message and a handle.


{% extends 'base.html' %}

{% block header %}
  <h1>{% block title %}Submit a message{% endblock %}</h1>
{% endblock %}

{% block content %}
  <form method="post">
    <label for="message">Your message:</label>
    <br>
    <!-- Message submission -->
    <input name="message" id="message"> 
    <br>
    <label for="handle">Your name or handle:</label>
    <br>
    <!-- Handle submission -->
    <input name="handle" id="handle"> 
    <br>
    <!-- Submit button -->
    <input type="submit" value="Submit message">
  </form>
  <!-- Thank you message -->
  {% if thanks %}
    Thank you for your submission!
  {% endif %}
{% endblock %}

The view.html File

The view.html file displays base.html, as well as five random messages.


{% extends 'base.html' %}

{% block header %}
  <h1>{% block title %}View messages{% endblock %}</h1>
{% endblock %}

{% block content %}
    <!-- If random messages were queried from database -->
  {% if random_messages %}
    <!-- For each tuple in random messages -->
    {% for tuple in random_messages %}
    <br>
    <!-- Message -->
    "{{tuple[2]}}"
    <br>
    <!-- Handle -->
    - <i>{{tuple[1]}}</i>
    <br>
    {% endfor %}
  {% endif %}
{% endblock %}

Screencaps

Below are some screencaps of the web app in action.

screencap-1.png

A user submitting a message.

screencap-2.png

A user viewing submitted messages.

Updated: