Saturday 21 December 2019

Drinking from the Flask part 1

Drinking from the Flask

This small project will integrate Python, Flask, JSON and .Net.

Task 1: Set up a JSON end point using Python and Flask
Task 2:  .Net application to read data from the end point
Task 3: Expand end points on the Python server for details
Task 4: Select and search for details via JSON calls.

Background

PythonAnywhere is an online (Platform as a Service) integrated Development Environment and web hosting service. One of its great advantages is that there is a free version - the free version has limitations on available libraries, calls etc, but is very useful if you have a need for somewhere to develop and test Python based web content.

Flask is a lightweight web framework written in Python. It has no database abstraction layer, and is suitable when you want a simple way of generating web content from lower power hardware.

It is available on the PythonAnywhere cloud based Python environment (there is a very helpful tutorial on the site which is worth having a look at. The tutorial is so good, I will just put a link to it rather than run through it again).

Filling the Flask

Python has numerous options for developing web sites and web content delivery. Two of the most popular are Flask and Django. For this case, I will be using Flask on PythonAnywhere.
At this point I will assume that you have gone through the setting up your first database and web based Flask site tutorial from the PythonAnywhere blog: https://blog.pythonanywhere.com/121/.

One of the great advantages of Python over a number of other popular languages is that you can really write once and reuse, so first we will write some test code in your Python IDE of choice (you could use the PythonAnywhere IDE, but I am using Thonny on my trusty Raspberry Pi).

The requirement is to generate a JSON document that contains a list of email addresses and subscriber IDs.

Start off by creating a Python file called subscriptions.py.
This will contain a class to hold a subscriber called Subscriber. Because we will be using this for testing, I have added a testFill method that returns a List of subscribers (with made up names).
The Subscriber class has a method called toJSON that packages up the contents of an instance in a JSON compatible form.

class Subscriber:
    def __init__(self,email_address,subscriptionid):
        self.email_address = email_address
        self.subscriptionid = subscriptionid

    def toJSON(self):
        return {"subscriber": {'emailaddress': self.email_address,
                     'subscriptionid': self.subscriptionid}}

    def testFill():
        subscriptionsList = []
        for ix in range(0,5):
            subscriber = Subscriber('email_'+str(ix)+'@tec.com',ix)
            subscriptionsList.append(subscriber)
        return subscriptionsList

To test this, create another file called testjson.py.
This imports the Subscriber class from the file subscriptions.py and the json class from flask.
It then prints the test data out. The sort keys and indent "pretty print" the text.

from subscriptions import Subscriber
from flask import json
print( json.dumps([e.toJSON() for e in Subscriber.testFill()], sort_keys=True, indent=4))

The results look like this:
[
    {
        "subscriber": {
            "emailaddress": "email_0@tec.com",
            "subscriptionid": 0
        }
    },
    {
        "subscriber": {
            "emailaddress": "email_1@tec.com",
            "subscriptionid": 1
        }
    },
    {
        "subscriber": {
            "emailaddress": "email_2@tec.com",
            "subscriptionid": 2
        }
    },
    {
        "subscriber": {
            "emailaddress": "email_3@tec.com",
            "subscriptionid": 3
        }
    },
    {
        "subscriber": {
            "emailaddress": "email_4@tec.com",
            "subscriptionid": 4
        }
    }
]
So having successfully generated the body of the JSON document, it is now on to the web delivery.

Pouring the Flask

If you have followed the tutorial from the PythonAnywhere blog, you will have a working web site.
Now you need to add some additional pieces to deliver the JSON document.

Log into PythonAnywhere.

Select the Web tab.

Scroll down to Code and on the row Source Code click on Go to directory.

I created a new subscriptions.py file and copied the contents (you could upload it, but it was short enough that that was not an issue). I have mentioned the write once, use many times joy of Python.

Now down to the business of delivering the JSON to your eager customers.

Right click on flask_app.py and open in a new tab.

This will contain the various pieces you have added as part of the tutorial, or may be empty if you have written it yourself.

To use the Subscriber class, you need to add an import at the top of the file (you can copy and paste the one from the testjson.py file.

You will need to create a suitable endpoint.

Using Flask, you add a decorator of the form @app.route('/somewhere').
This is followed by the function that will be called when the user goes to the page somewhere on your site.

The function creates the output content from the testFill method of the Subscriber class (as previously) and then wraps it in a Subscribers class.
It then sets up the response object and returns it.

...
@app.route('/subscribers')
def testJson():
    content=json.dumps([e.toJSON() for e in Subscriber.testFill()])
    content="{\"Subscribers\":"+content+"}"
    response = app.response_class(
        response=content,
        status=200,
        mimetype='application/json'
    )
    return response
...

So, to view your work you just need to go to http://<yourusername>.pythonanywhere.com/subscribers

Your browser should display something like:
{"Subscribers":[{"subscriber": {"emailaddress": "email_0@tec.com", "subscriptionid": 0}}, {"subscriber": {"emailaddress": "email_1@tec.com", "subscriptionid": 1}}, {"subscriber": {"emailaddress": "email_2@tec.com", "subscriptionid": 2}}, {"subscriber": {"emailaddress": "email_3@tec.com", "subscriptionid": 3}}, {"subscriber": {"emailaddress": "email_4@tec.com", "subscriptionid": 4}}]}

Next: Drinking from the Flask with .Net

References