# Introduction to Python: HTTP (Flask) So far, we've learnt Python fundamentals, worked with data, files and more importantly, basic data structures like `csv` and `json`. JSON is a very popular format for now only storing, but transporting data in web HTTP applications. Files are important because we may need to read configuration files for our application. One application could make a web request to ask for customer data from our application. By sending back JSON, the receiving application can easily process the data it gets. Be sure to checkout [Part 2: Files](../part-2.files) As well as [Part 3: JSON](../part-3.json) ## Python Dev Environment The same as Part 1, we start with a [dockerfile](./dockerfile) where we declare our version of `python`. ``` FROM python:3.9.6-alpine3.13 as dev WORKDIR /work ``` Let's build and start our container: ``` cd python\introduction\part-4.http docker build --target dev . -t python docker run -it -v ${PWD}:/work python sh /work # python --version Python 3.9.6 ``` ## Our application We're going to use what we've learnt in part 1,2 & 3 and create our customer app that stores customer data Firstly we have to import our dependencies: ``` import os.path import csv import json ``` Then we have a class to define what a customer looks like: ``` class Customer: def __init__(self, c="",f="",l=""): self.customerID = c self.firstName = f self.lastName = l def fullName(self): return self.firstName + " " + self.lastName ``` Then we need a function which returns our customers: ``` def getCustomers(): if os.path.isfile("customers.json"): with open('customers.json', newline='') as customerFile: data = customerFile.read() customers = json.loads(data) return customers else: return {} ``` Here is a function to return a specific customer: ``` def getCustomer(customerID): customer = getCustomers() return customer[customerID] ``` And finally a function for updating our customers: ``` def updateCustomers(customers): with open('customers.json', 'w', newline='') as customerFile: customerJSON = json.dumps(customers) customerFile.write(customerJSON) ``` In the previous episode, we've created a `json` file to hold all our customers. We've learnt how to read and write to file and temporarily use the file for our storage. ``` { "a": { "customerID": "a", "firstName": "James", "lastName": "Baker" }, "b": { "customerID": "b", "firstName": "Jonathan", "lastName": "D" }, "c": { "customerID": "c", "firstName": "Aleem", "lastName": "Janmohamed" }, "d": { "customerID": "d", "firstName": "Ivo", "lastName": "Galic" }, "e": { "customerID": "e", "firstName": "Joel", "lastName": "Griffiths" }, "f": { "customerID": "f", "firstName": "Michael", "lastName": "Spinks" }, "g": { "customerID": "g", "firstName": "Victor", "lastName": "Savkov" } } ``` Now that we have our customer data, we can read and update the data with our two simple functions: ``` customers = getCustomers() print(customers) ``` Let's add a customer and write it back to file: ``` customers["h"] = Customer("h", "Marcel", "Dempers").__dict__ updateCustomers(customers) ``` Now `customers.json` has the new entry if we rerun our code: ``` python src/app.py ``` ## Flask Checkout official Flask documentation [here](https://flask.palletsprojects.com/en/2.0.x/) A minimal flask application looks like this: ``` from flask import Flask app = Flask(__name__) @app.route("/") def hello_world(): return "
Hello, World!
" ``` To get this to work, we need to look at Pythons Library system, or `pip` ## External Packages If we look at the `from flask import Flask` statement, it assumes we have a `flask` dependency. Our previous import statements worked, because they are built-in libraries in python. Flask is an external package. External packages are managed by [pip](https://pypi.org/project/pip/) We may use `pip` to install `Flask`. If we need to connect to databases, we may install packages to do so. Like a `mysql` or a `redis` package. With `pip`, we define our dependencies in a `requirements.txt` file. We can check for the latest version of `Flask` [here](https://pypi.org/project/Flask/) We can also use `pip install` commands to install dependencies. However, this means we need a new `pip install` command for every dependency which will grow as our application and needs grow. Best is to use a `requirements.txt` file. Let's create a `requirements.txt` file: ``` Flask == 2.0.2 ``` We can install our dependencies using: ``` pip install -r src/requirements.txt ``` Let's implement the minimal example we posted above. To run our application, note that the `app.py` runs as per usual.Hello, get_customers!
" @app.route("/get/Hello, get!
" @app.route("/add", methods=['POST']) def add_customer(customer): return "Hello, add!
" ``` Now that we've built our URLs using routes, next we need to understand HTTP methods ## HTTP Methods There are a number of HTTP methods for web services, popular ones being `POST` and `GET` `GET` method is for general retrieval of data `POST` method is for passing data to our service Let's setup each of our routes with dedicated HTTP Methods ``` @app.route("/", methods=['GET']) def get_customers(): return "Hello, get_customers!
" @app.route("/get/Hello, get!
" @app.route("/add", methods=['POST']) def add_customer(): return "Hello, add!
" ``` Now we can see if we access `http://localhost:5000/add` We get: `Method Not Allowed` , because it only accepts `POST` and browser by default, does `GET` Let's fill out our routes ### Get Customers ``` @app.route("/", methods=['GET']) def get_customers(): customers = getCustomers() return json.dumps(customers) ``` ### Get Customer ``` @app.route("/get/