View on GitHub


A microblog application powered by Flask and Neo4j.

Download this project as a .zip file Download this project as a tar.gz file

Add a Post

Once a user has successfully logged in or registered, they’re redirected to the / view, the home page. When session.username is not None, a form is displayed that allows the user to share a post. This form sends a POST request with the title, text, and tags of the post to the /add_post/<username> view, where <username> is replaced with the logged-in-user’s username. In, this view is defined by the following:

@app.route('/add_post', methods=['POST'])
def add_post():
    title = request.form['title']
    tags = request.form['tags']
    text = request.form['text']

    if not title:
        flash('You must give your post a title.')
    elif not tags:
        flash('You must give your post at least one tag.')
    elif not text:
        flash('You must give your post a text body.')
        User(session['username']).add_post(title, tags, text)

    return redirect(url_for('index'))

The title, text, and tags that were sent with the POST request are accessed and checked to make sure they aren’t empty. If it all checks out, the User.add_post() method is called with title, text, and tags as arguments. The add_post() method is defined in the User class like so:

class User:


    def add_post(self, title, tags, text):
        user = self.find()
        post = Node(
        rel = Relationship(user, "PUBLISHED", post)

        tags = [x.strip() for x in tags.lower().split(',')]
        for t in set(tags):
            tag = graph.merge_one("Tag", "name", t)
            rel = Relationship(tag, "TAGGED", post)

The user is found in the database with User.find(), which returns a py2neo.Node object. Then, another Node object post is created with the shown properties. A random id is generated with the uuid package’s uuid4() method, and the timestamp and date are set with functions I defined elsewhere in

def timestamp():
    epoch = datetime.utcfromtimestamp(0)
    now =
    delta = now - epoch
    return delta.total_seconds()

def date():

With both the user and post variables, we can create a (:User)-[:PUBLISHED]->(:Post) relationship in the graph by passing a py2neo.Relationship object to Graph.create(). Finally, the tags are split on commas and lowercased. For each of these tags, a relationship (:Tag)-[:TAGGED]->(:Post) is created. We use the Graph.merge_one() method to ensure we are finding or creating a Tag node with the given name property.

The form where a user adds a new post is located in index.html:

{% extends "layout.html" %}
{% block body %}

  {% if session.username %}
    <h3>Share New Post</h3>
    <form action="{{ url_for('add_post') }}" method="post">
            <dd><input type="text" size="30" name="title"></dd>
            <dt>Tags (separated by commas):</dt>
            <dd><input type="text" size="30" name="tags"></dd>
            <dd><textarea name="text" rows="5" cols="40"></textarea></dd>
        <input type="submit" value="Share">
  {% endif %}


<h3>Today's Recent Posts</h3>
{% include "display_posts.html" %}

{% endblock %}

Next: Display Posts