{"id":10439,"date":"2019-01-29T06:04:08","date_gmt":"2019-01-29T11:04:08","guid":{"rendered":"https:\/\/qxf2.com\/blog\/?p=10439"},"modified":"2023-05-11T04:27:26","modified_gmt":"2023-05-11T08:27:26","slug":"sample-solid-app-on-python-flask","status":"publish","type":"post","link":"https:\/\/qxf2.com\/blog\/sample-solid-app-on-python-flask\/","title":{"rendered":"Sample Solid application on Python Flask"},"content":{"rendered":"<p>Recently, we stumbled upon <a href=\"https:\/\/www.inrupt.com\/solid\">Inrupt&#8217;s Solid<\/a> and after going through their fundamental documentation, we became keen on building a sample solid application and get a better understanding of it. All of Solid&#8217;s examples are built on JQuery and NodeJS. We like Python and so we wanted to build some Python-based examples. This post will focus on how to use Python to load, parse and traverse <a href=\"https:\/\/www.inrupt.com\/solid\">Solid<\/a> data. <\/p>\n<hr\/>\n<p>Before going into deep details, lets first understand what <a href=\"https:\/\/www.inrupt.com\/solid\">Solid <\/a>is about and what kind of data it deals with.<\/p>\n<h3>Solid Overview<\/h3>\n<p><a href=\"https:\/\/www.inrupt.com\/solid\">Solid <\/a>(derived from &#8220;social linked data&#8221;) is a decentralized platform for social Web applications. In the Solid platform, each user stores their data in personal online datastore (or pod) served by different public pod servers and identity providers. In solid, the applications and data are decoupled. Applications built using Solid platform do not have their own data but they can access data which is stored in a place of user&#8217;s choice using different protocols, authentication and access control system. <\/p>\n<p>Before going into details of our code, we will first understand about few most commonly used terms in Solid which we will be referring in below sections like <a href=\"https:\/\/solidproject.org\/users\/get-a-pod\">POD<\/a>, <a href=\"https:\/\/www.w3.org\/2005\/Incubator\/webid\/spec\/identity\/\">WebID<\/a>, <a href=\"https:\/\/www.w3.org\/DesignIssues\/LinkedData.html\">Linked data<\/a>, <a href=\"https:\/\/www.w3.org\/2001\/sw\/RDFCore\/Schema\/200203\/\">Namespaces<\/a> and <a href=\"https:\/\/en.wikipedia.org\/wiki\/Resource_Description_Framework\">RDF<\/a>(Resource Description framework) which is the data model for Linked Data.<\/p>\n<hr\/>\n<h3>POD(Personal online datastore)<\/h3>\n<p> In Solid platform, each user stores their data in a personal online datastore (pod) that resides on a pod server. You can give applications read\/write access to parts of your data in POD. You can learn more about Solid POD&#8217;s <a href=\"https:\/\/solidproject.org\/users\/get-a-pod\">here<\/a><\/p>\n<hr\/>\n<h3>WebID<\/h3>\n<p> Solid uses WebID URIs as universal usernames. When you register with Solid, you get a public Solid POD URL(which is like the homepage for your Solid pod) and public Solid WebID which acts as a global ID that you can use to identify and authenticate yourself with other PODs across the world. In Solid, the registered identity provider stores the user&#8217;s profile document in Turtle and RDF formats. You can learn more about WebID <a href=\"https:\/\/www.w3.org\/2005\/Incubator\/webid\/spec\/identity\/\">here<\/a><\/p>\n<hr\/>\n<h3>Linked Data<\/h3>\n<p>In Solid platform, users can store any piece of the data in their pods and this data in one pod can be linked with data in different pods. This connected data is referred to as Linked Data. You can learn more about Linked Data <a href=\"https:\/\/www.w3.org\/DesignIssues\/LinkedData.html\">here<\/a><\/p>\n<hr\/>\n<h3>Namespaces in RDF<\/h3>\n<p>RDFLib provides several short-cuts to working with many URIs in the same namespace. The purpose of the namespace is simply to avoid name conflicts with tags of the same name. You can refer <a href=\"https:\/\/www.w3.org\/2001\/sw\/RDFCore\/Schema\/200203\/\">here<\/a> for more details on RDF Vocabulary and namespaces<\/p>\n<hr\/>\n<h3>RDF &#8211; the data model for Linked Data<\/h3>\n<p>Linked Data is typically represented in RDF, the Resource Description Framework. It is based on the idea of making statements about resources in expressions of the form subject\u2013predicate\u2013object, known as triples. RDF has different syntaxes like Turtle, N-Triples, N3, JSON-LD, RDF\/XML etc., You can learn more about RDF <a href=\"https:\/\/en.wikipedia.org\/wiki\/Resource_Description_Framework\">here<\/a><\/p>\n<hr\/>\n<h3>Sample Python solid profile viewer application<\/h3>\n<p>Based on the example <a href=\"https:\/\/github.com\/solid\/profile-viewer-tutorial\">profile viewer<\/a> app, we built a sample python solid application using flask. This profile viewer will show data from different people&#8217;s profiles based on the given WebID. We used python <a href=\"https:\/\/github.com\/RDFLib\/rdflib\">rdflib <\/a>library for reading Solid data. <\/p>\n<p><strong>Pre-requisites<\/strong>: In order to read and write Solid data, we need our own Solid POD and identity. We created a POD from <a href=\"https:\/\/solidproject.org\/users\/get-a-pod\">Get a Solid POD<\/a> <\/p>\n<p>To brief, our sample solid python web application does the following: <\/p>\n<p>1. Gets the user input &#8216;Profile&#8217; webID using the HTTP Get method.<br \/>\n2. Creates an RDF Graph<br \/>\n3. Based on the webID, reads data from a Solid pod.<br \/>\n4. Parse the data returned into a graph<br \/>\n5. Get the friends list for the given webID<br \/>\n6. Display the returned friends webID list on the browser.<\/p>\n<p>To get started, we need to download and install some Python modules. While there are several Python modules for working with RDF data, this post will focus on <a href=\"https:\/\/github.com\/RDFLib\/rdflib\">RDFLib<\/a>. The RDFLib module provides a powerful set of tools for creating, parsing, traversing and editing RDF data. It allows us to interact with Linked Data stored in Solid pods. <\/p>\n<p>RDFLib aims to be a pythonic RDF API, a Graph is a python collection of RDF Subject, Predicate, Object Triples:<\/p>\n<p>Let&#8217;s dive into the code. We created a file named &#8216;<em>sample_python_solid.py<\/em>&#8216; with following content:<\/p>\n<pre lang='python'>\r\n\"\"\"\r\nThis is a Flask application for Inrupt Solid profile viewer. \r\n\r\n\"\"\"\r\n\r\nfrom flask import Flask, jsonify, render_template, request\r\nimport json\r\nimport logging\r\nimport urllib2\r\nimport rdflib   \r\nfrom rdflib import URIRef,Graph,RDF\r\nfrom rdflib.namespace import FOAF\r\n\r\n\r\napp = Flask(__name__)\r\n\r\ndef post_friends_list(uri):\r\n    \"create,parse graph and get the friends list for the given URI\"\r\n    # Create a Empty graph      \r\n    graph = rdflib.Graph()   \r\n    graph.parse(uri)   \r\n    for person in graph[: RDF.type: FOAF.Person]:\r\n        name = graph.value(person, FOAF.name)             \r\n        friends = list(graph[person:FOAF.knows])\r\n        app.logger.info('%s friends', friends)\r\n        if friends:\r\n            app.logger.info(\"%s's friends:\", graph.value(person, FOAF.name))           \r\n\r\n        return friends,name          \r\n\r\n\r\n@app.route(\"\/\", methods=['GET','POST'])\r\n@app.route(\"\/view\", methods=['GET','POST'])\r\ndef view():\r\n    \"Endpoint for getting the friends list for the given URI\"\r\n    if request.method == 'GET':\r\n        #return the form\r\n        return render_template('sample_solid.html')\r\n    if request.method == 'POST':\r\n        #return the answer\r\n        uri = request.form.get('profile')        \r\n        result,name = post_friends_list(uri)        \r\n        api_response = {\"answer\": result, \r\n                        \"name\": name}        \r\n        return jsonify(api_response)\r\n            \r\n   \r\n#---START OF SCRIPT\r\nif __name__ == '__main__':\r\n    app.run(host='127.0.0.1', port=6464, debug= True)\r\n<\/pre>\n<p>First, we make a Flask object, use the \u2018route\u2019 decorator functions to define GET (Render a template when the route is triggered with GET method) and POST (post URI to that URL). Then, call post_friends_list() function(which we will be discussing in below section) and finally a \u2018run\u2019 function when we run it locally (which you can confirm by calling python sample_python_solid.py and visiting localhost:6464 in your browser.)<\/p>\n<hr\/>\n<h3>Using built-in RDFLib functions<\/h3>\n<p> In the above code, you can see a method called <em>post_friends_list()<\/em>, which is the actual python code in which we used <a href=\"https:\/\/github.com\/RDFLib\/rdflib\">RDFLib<\/a> libraries to create a RDF Graph. A Graph is a python collection of RDF Subject, Predicate, Object Triples. It is like a database which is arbitrary in terms of what is related to what. The way you parse RDF with rdflib is you create a Graph, which is a sort of empty holder for data. Imagine this as a big container for data, and you can throw into the container as much data as you like, then just filter out the bits you want.<\/p>\n<p>First we should import the <a href=\"https:\/\/github.com\/RDFLib\/rdflib\/blob\/master\/rdflib\/graph.py\">Graph<\/a> class from the rdflib package and create a Graph instance as shown below:<\/p>\n<pre lang='python'>\r\n\r\nfrom rdflib import URIRef, Graph\r\n\r\ngraph = rdflib.Graph()\r\n\r\n<\/pre>\n<p>The &#8216;graph&#8217; variable now has an empty graph. Now we should load some data into the graph. The graph object has a method called &#8216;parse&#8217; which allows you to give it a file name from your local system or an HTTP URI and it will try to load data from that source. In our case, we&#8217;ll load in data to parse a specified URI which the user inputs in the URL.<\/p>\n<p>To fetch user&#8217;s profile document, we are iterating over the triples and getting the name of the person using <a href=\"http:\/\/xmlns.com\/foaf\/spec\/\">FOAF<\/a>(Friend of a Friend) Vocabulary. Below are the steps performed:<\/p>\n<p>1. Loop over each FOAF: Person in the graph(RDF.type: FOAF.Person)<br \/>\n2. Using graph.value() to get the person&#8217;s name<br \/>\n3. Fetch the list of friends using graph[person:FOAF.knows] attribute.<br \/>\n4. Return the user full name and his friend&#8217;s webID list.<\/p>\n<figure id=\"attachment_10495\" aria-describedby=\"caption-attachment-10495\" style=\"width: 1024px\" class=\"wp-caption aligncenter\"><a href=\"https:\/\/qxf2.com\/blog\/wp-content\/uploads\/2018\/12\/solid_python_application.png\" data-rel=\"lightbox-image-0\" data-rl_title=\"\" data-rl_caption=\"\" title=\"\"><img loading=\"lazy\" decoding=\"async\" src=\"https:\/\/qxf2.com\/blog\/wp-content\/uploads\/2018\/12\/solid_python_application-1024x454.png\" alt=\"\" width=\"1024\" height=\"454\" class=\"size-large wp-image-10495\" srcset=\"https:\/\/qxf2.com\/blog\/wp-content\/uploads\/2018\/12\/solid_python_application-1024x454.png 1024w, https:\/\/qxf2.com\/blog\/wp-content\/uploads\/2018\/12\/solid_python_application-300x133.png 300w, https:\/\/qxf2.com\/blog\/wp-content\/uploads\/2018\/12\/solid_python_application-768x340.png 768w, https:\/\/qxf2.com\/blog\/wp-content\/uploads\/2018\/12\/solid_python_application.png 1106w\" sizes=\"auto, (max-width: 1024px) 100vw, 1024px\" \/><\/a><figcaption id=\"caption-attachment-10495\" class=\"wp-caption-text\">Sample Solid Python Application<\/figcaption><\/figure>\n<hr\/>\n<h3>About our HTML page<\/h3>\n<p> We have a input field which accepts the webID from the user. When clicked on the View button the user information(Full Name and friend&#8217;s list) is loaded in the browser page. We have written Javascript code to make the friend&#8217;s webID clickable. When a webID link is clicked from the friend&#8217;s list, that person&#8217;s webID is loaded into the Profile input field and when the user clicks on the View Button, the name of his friends is loaded in the page. This information is fetched directly from the friend&#8217;s pods. Note:-  You need to add a few friends to your profile before trying this. <\/p>\n<hr\/>\n<p>You can find the code associated with this post on Qxf2\u2019s <a href=\"https:\/\/github.com\/qxf2\/sample-python-solid-app\">GitHub<\/a>. We hope this article helps you get started with implementing Solid web applications using python.<\/p>\n<hr\/>\n<h3>References<\/h3>\n<p>1. <a href=\"https:\/\/solid.inrupt.com\/docs\/getting-started\">Solid &#8211; Getting Started<\/a><br \/>\n2. <a href=\"https:\/\/rdflib.readthedocs.io\/en\/stable\/\">RDFLib Documentation<\/a><br \/>\n3. <a href=\"https:\/\/www.oclc.org\/developer\/news\/2016\/making-sense-of-linked-data-with-python.en.html\">Making sense of linked data with python<\/a> <\/p>\n","protected":false},"excerpt":{"rendered":"<p>Recently, we stumbled upon Inrupt&#8217;s Solid and after going through their fundamental documentation, we became keen on building a sample solid application and get a better understanding of it. All of Solid&#8217;s examples are built on JQuery and NodeJS. We like Python and so we wanted to build some Python-based examples. This post will focus on how to use Python [&hellip;]<\/p>\n","protected":false},"author":16,"featured_media":0,"comment_status":"open","ping_status":"open","sticky":false,"template":"","format":"standard","meta":{"footnotes":""},"categories":[172,182,18,183],"tags":[],"class_list":["post-10439","post","type-post","status-publish","format-standard","hentry","category-flask","category-inrupt-solid","category-python","category-rdf"],"_links":{"self":[{"href":"https:\/\/qxf2.com\/blog\/wp-json\/wp\/v2\/posts\/10439","targetHints":{"allow":["GET"]}}],"collection":[{"href":"https:\/\/qxf2.com\/blog\/wp-json\/wp\/v2\/posts"}],"about":[{"href":"https:\/\/qxf2.com\/blog\/wp-json\/wp\/v2\/types\/post"}],"author":[{"embeddable":true,"href":"https:\/\/qxf2.com\/blog\/wp-json\/wp\/v2\/users\/16"}],"replies":[{"embeddable":true,"href":"https:\/\/qxf2.com\/blog\/wp-json\/wp\/v2\/comments?post=10439"}],"version-history":[{"count":49,"href":"https:\/\/qxf2.com\/blog\/wp-json\/wp\/v2\/posts\/10439\/revisions"}],"predecessor-version":[{"id":18303,"href":"https:\/\/qxf2.com\/blog\/wp-json\/wp\/v2\/posts\/10439\/revisions\/18303"}],"wp:attachment":[{"href":"https:\/\/qxf2.com\/blog\/wp-json\/wp\/v2\/media?parent=10439"}],"wp:term":[{"taxonomy":"category","embeddable":true,"href":"https:\/\/qxf2.com\/blog\/wp-json\/wp\/v2\/categories?post=10439"},{"taxonomy":"post_tag","embeddable":true,"href":"https:\/\/qxf2.com\/blog\/wp-json\/wp\/v2\/tags?post=10439"}],"curies":[{"name":"wp","href":"https:\/\/api.w.org\/{rel}","templated":true}]}}