Making Semantic Web Applications With Flask: Starting With FOAF

WHEN INTRODUCING the Semantic Web, Sir Tim Berners-Lee asked us to share not just our documents, but also our data. The Semantic Web uses the internet as a database. A big, messy, poorly organised database with latency and availability issues. But this is still better than the big, messy, poorly organised collection of documents with latency and availability issues that currently comprises the world-wide-web. Plus, you can exploit it in some really useful ways.

As web-developers we use databases on a regular basis. We make them to suit our own needs, use our own terms, and manage them ourselves. On the Semantic Web, we need to link all our data together, if we tried this with all our databases we’d likely find don’t align very nicely. So in the Semantic Web we borrow from ontology. An ontology is designed to represent the truth, as opposed to fulfil our needs, they define terms so everyone has a common language, and they are created by teams of experts.

We’re going to use an ontology called “FOAF”, it’s one of the early explorations into semantic web and a good place to start. We’ll create our own FOAF file and make it available via Flask. We’ll then consume our own data in our application and make it discoverable for others. In later posts we’ll look at how Google, Facebook and Twitter consume semantic web data and how we can consume data from other sources too.

Get FOAF

YOU CAN read all the FOAF docs for the FOAF terminology and write out your own FOAF.rdf file in XML. But I’d recommend you visit foaf-a-matic and use the free tool Leigh Dodds created to generate one. You can always add to it later.

The file you’ll get will be in XML, you should save it as foaf.rdf. Not all semantic web documents are in XML, you can also use JSON-LD and there’s N3 or Turtle if you’d like something with a YAML feel. But this is an old tool, so XML it is. This is an excerpt from my file.

<foaf:Person rdf:ID="me">
  <foaf:name>Paul Brown</foaf:name>
  <foaf:title>Mr</foaf:title>
  <foaf:givenname>Paul</foaf:givenname>
  <foaf:family_name>Brown</foaf:family_name>
  <foaf:homepage rdf:resource="http://www.paulbrownmagic.com"/>
</foaf:Person>

Get Flask

FLASK IS a light-weight web development for Python, we’re using it because it’s unopinionated, meaning it’s easy us to work with RDF data.

We’ll go through what you need for this application, but if Flask is new to you, I’d recommend their tutorial.

First we need to pip install Flask.

:~$ pip3 install flask

Next, setup the directory structure. I usually have a directory for all my rdf in static, along with ones for css, javascript, images etc.

foaf_flask/
|-- dev.py
|-- foaf_flask/
|   |-- main.py
|   |-- templates/
|       |-- index.html
|   |-- static/
|       |-- rdf/
|           |-- foaf.rdf

Let’s start with some code. dev.py is to run inbuilt development server, when you actually deploy a Flask application you’ll want something better but it’ll do for now. This file is our entry point and just runs that app.

from foaf_flask.main import app

if __name__ == "__main__":
    app.run(debug=True)

Now for the real code, this is main.py. It’s your Flask “Hello, world” with a template.

from flask import Flask, render_template
app = Flask(__name__)

@app.route("/")
def home_page():
    return render_template("index.html")

This is the template index.html.

<!DOCTYPE html>
<html>
    <head>
        <meta charset="utf-8">
        <title>FOAF With Flask</title>
    </head>
    <body>
    <h1>Hello, world!</h1>
    </body>
</html>

Run the app, open your browser at http://127.0.0.1:5000 and you should see “Hello, world!”. If you go to http://127.0.0.1:5000/static/rdf/foaf.rdf you will get your FOAF. Congratulations, you can now publish data to the semantic web!

:~$ python3 dev.py

Consume Your Data

WE’VE GOT some data, we may as well use it. Plus, this demonstrates one of the dreams of the semantic web. Imagine you got married and changed your name. How many accounts would you need to update? Wouldn’t it be easier to just update your FOAF and allow all your accounts to get their information from there?

To consume our data we’ll use rdflib, which is Python’s library for handling your semantic web data. We’ll read our FOAF into it, run a SPARQL query against it, and send the result to our template. First, we need to install rdflib.

:~$ pip3 install rdflib

Now let’s update main.py. The SPARQL query here makes sure we’re getting the foaf:givenname of a foaf:Person. It assumes it will be returning rows of results, we know we only need the first row, so we only return that from get_me().

from flask import Flask, render_template
from rdflib import Graph
from rdflib.namespace import FOAF

app = Flask(__name__)
foaf = Graph()
foaf.parse("flask_foaf/static/rdf/foaf.rdf")


def get_me():
    res = foaf.query("""SELECT DISTINCT ?fname
                     WHERE {
                     ?me a foaf:Person .
                     ?me foaf:givenname ?fname .
                     }
                     """, initNs={"foaf": FOAF})
    return list(res)[0]

@app.route("/")
def home_page():
    return render_template("index.html",
                           me= get_me()
                           )

In the template we can access the ?fname using object notation: me.fname. Here’s the updated template.

<!DOCTYPE html>
<html>
    <head>
        <meta charset="utf-8">
        <title>FOAF With Flask</title>
    </head>
    <body>
    <h1>Hello, world!</h1>
    <p> My name is {{ me.fname }}.</p>
    </body>
</html>

Run the application and you’ll see your name. Congratulations, you can query and use your FOAF file data. To adapt your query, look at the terms in the FOAF docs. Can you get your full name?

Make Your Data Discoverable

THE LAST step is to help machines and people find your FOAF file. The recommended method is to use the link tag in the head of your HTML. That’ll help machines, but I’d also recommend putting a visible link to it for people, like I have in my footer. I’ve provided you with the link tag to put in the <head></head> of your index.html.

<link href="{{ url_for('static', filename='rdf/foaf.rdf', _external=True) }}" rel="meta" title="FOAF" type="application/rdf+xml">

Conclusion

YOU CAN now host an RDF file, SPARQL query it, use that data in your template and make the RDF file discoverable. There’s still a lot to learn! I’d recommend adding some more information to your FOAF using their terms and playing with SPARQL queries on your FOAF file for now.

In later posts we’ll look at including the data in your HTML, who consumes this data and how you can exploit that, other ways to serve your data and how you can consume other’s data. If you publish your FOAF, let me know in the comments.

Until next time, happy coding. Paul

Get The Code

THE CODE for this tutorial is available on github at: https://github.com/PaulBrownMagic/flask_foaf

*[FOAF]: Friend Of A Friend