Intro to Python frameworks & Django

Tips for navigating the slides:
  • Press O or Escape for overview mode.
  • Visit this link for a nice printable version
  • Press the copy icon on the upper right of code blocks to copy the code

Class outline:

  • Review
  • About Python frameworks
  • About Django
  • Django MVT
  • Getting started with Django

Review: HTTP requests & JSON

What is HTTP?

Hypertext Transfer Protocol (HTTP) is how we send data and files around the Web

HTTP works as a request-response protocol between a client and server.

  • Client could be a web browser (operated by a human) or an application (like a computer running a Python program)
  • Server could be a computer with files (like HTML) stored on it, or an application serving up data through an API

HTTP requests

An HTTP request consists of:

  1. Method (required) GET, PUT, POST, etc
  2. Request URI (required) Full URI, including any query parameters
  3. Header(s) (optional) Ex: API token)
  4. Body (optional) Ex: data you want to send

                        curl # Command-line tool used to send HTTP requests
                        -X GET # Method
                        -H 'Accept: application/json' # Header
                        # Request URI
                        'https://api.open-meteo.com/v1/forecast?latitude=43.07&longitude=-89.40&hourly=temperature_2m'
                    

HTTP requests

Common request methods

GETRetreive data from a specified resource
POSTSend data to a server (usually via an API) to create/overwrite a resource
PUTSend data to a server (usually via an API) to create/update a resource
DELETEDelete a specified resource

Requests module

The Requests module is a third-party library, and is the de-facto standard for sending HTTP requests and receiving responses using Python.

On your own machine, you need to install requests before you can import it into Python files


                        pip install requests
                    

Requests module documentation

Requests module

In Replit, install requests by clicking Tools > Packages, then searching for "requests"

Making a GET request

requests.get() sends an HTTP request and returns an HTTP response object


                        import requests
                        response = requests.get("https://girldevelopit.com")
                        print(vars(response))
                    

What's in a Response?

Lots of stuff! See full list. The values we're typically concerned about are:

.status_codeStatus code of the request (200 OK, 404 Not found, etc)
.text, .json or .rawBody of the response (stored in different attributes, depending on the type of response
.headersHTTP response headers, with details about the response content and where it came from

What's in a Response?

Let's look at some response values


                            import requests

                            response = requests.get("https://girldevelopit.com")
                            print(response.status_code) # HTTP status code (200)
                            print(response.headers) # Content-type tells us what kind of response this is (text/html)
                            print(response.text) # The full body of the response (HTML, in this case)
                        

What's an API?

An Application Programming Interface (API) is a way for 2 separate computer systems to communicate. Essentially, it's a set of rules for retrieving, creating, updating and/or deleting data in another system.

There are many different types of APIs, but on the Web we're typically talking about RESTful APIs, which allow 2 applications to exchange data securely over the Internet. RESTful APIs use URIs to identify resources.

The NASA APOD API

NASA posts an Astronomy Picture of the Day each day, which is also available via an API. To use this API, you first need to register for a key at https://api.nasa.gov

The NASA APOD API

After registering, you should recieve a key, along with a sample request.

Query parameters

In the NASA API, your key is added as a query paramter


                        ?api_key=eIkpQYXKa6mq1J75qPMYc0Rvit3K8wNaytEJCnTn&start_date=2023-01-01
                    

Query parameters ("params") are key/value pairs that allow adding extra context to a URL.

  • Query param portion of a URL begins with ?
  • Each additional param is preceded with &

                        https://api.nasa.gov/planetary/apod?api_key=eIkpQYXKa6mq1J75qPMYc0Rvit3K8wNaytEJCnTn&start_date=2023-01-01
                    

Params are specific to seach site/app/API - there's no universal set of available params

The NASA APOD API

Let's run this in Python


                        import requests

                        # per NASA API docs, we need to pass the key as a query parameter
                        params = {'api_key': 'eIkpQYXKa6mq1J75qPMYc0Rvit3K8wNaytEJCnTn'}
                        response = requests.get("https://api.nasa.gov/planetary/apod", params=params)
                        print(response.status_code)
                        print(response.headers)
                    

About JSON

Javascript Object Notation (JSON) is an open standard file format that stores data in key/value pairs. It looks a lot like a Python dictionary!

Requests has a built-in .json() method for parsing JSON responses, and Python has a built-in JSON library, too.


                        import requests
                        params = {'api_key': 'eIkpQYXKa6mq1J75qPMYc0Rvit3K8wNaytEJCnTn'}
                        response = requests.get("https://api.nasa.gov/planetary/apod", params=params)
                        print(response.json())
                    

JSON example


                        {
                            'copyright': 'Mike Selby',
                            'date': '2023-02-04',
                            'explanation': 'Centered in this colorful cosmic canvas, NGC 2626 is a beautiful, bright, blue reflection nebula in the southern Milky Way. Next to an obscuring dust cloud and surrounded by reddish hydrogen emission from large H II region RCW 27 it lies within a complex of dusty molecular clouds known as the Vela Molecular Ridge. NGC 2626 is itself a cloud of interstellar dust reflecting blue light from the young hot embedded star visible within the nebula. But astronomical explorations reveal many other young stars and associated nebulae in the star-forming region. NGC 2626 is about 3,200 light-years away. At that distance this telescopic field of view would span about 30 light-years along the Vela Molecular Ridge.',
                            'hdurl': 'https://apod.nasa.gov/apod/image/2302/NGC_2626_CDK_700_II_20_Jan_2023.jpg',
                            'media_type': 'image',
                            'service_version': 'v1',
                            'title': 'NGC 2626 along the Vela Molecular Ridge',
                            'url': 'https://apod.nasa.gov/apod/image/2302/NGC_2626_CDK_700_II_20_Jan_2023_1024.jpg'
                        }
                    

Accessing JSON values

Once the response values are parsed as JSON, we can treat it like a dictionary and access individual fields with bracket notation.


                        import requests
                        params = {'api_key': 'eIkpQYXKa6mq1J75qPMYc0Rvit3K8wNaytEJCnTn'}
                        response = requests.get("https://api.nasa.gov/planetary/apod", params=params)
                        json = response.json()
                        url = json['url']
                        print(url)
                    

HTTP status exceptions

Requests includes custom exception types, such as HTTP error, which covers issues like 404 not found and 403 access denied (bad credentials).

Requests does not automatically raise HTTP exceptions; we need to do that explicitly with the .raise_for_status() method and handle the exception.

Handling HTTP errors


                        import requests

                        params = {'api_key': 'eIkpQYXKa6mq1J75qPMYc0Rvit3K8wNaytEJCnTn'}

                        try:
                            response = requests.get("https://api.nasa.gov/planetary/apo", params=params)
                            response.raise_for_status()
                            json = response.json()
                            url = json['url']
                            print(url)
                        except requests.exceptions.HTTPError as e:
                            print("Oh no, an error happened: ", e)
                    

Exercise review: Requests

Class10Ex1Requests

Python frameworks

What's a framework?

Software frameworks are packages of starter code that you can build on. They're often used to develop web applications quickly. Frameworks do things like:

  • Provide code for common pieces of functionality, like serving web pages and authenticating users
  • Help you follow security best practices without having to be a web security expert
  • Allow you to focus on building functionality that's unique to your app

How is a framework different from a package/module?

  • Modules that we import into Python (ex, Requests) are smaller bundles of code that serve a very specific purpose. They are building blocks that help us create larger apps.
  • Frameworks are larger packages of code which include all the basic parts needed for a full web application. We can still add modules as needed to extend a framework!

Python web app frameworks

There are many Python frameworks out there! The 2 most popular general-purpose frameworks for web applications are:

Both allow you to build web applications and/or APIs, and both have a robust extension ecosystem

Django

Django features

In this class, we'll use Django. Its features include:

  • Built-in web server for development and testing
  • Functionality for processing HTTP requests with custom logic
  • Template system for displaying dynamic web pages to users
  • Database connectivity + built-in methods for reading/writing
  • Data modeling functionality to support converting between database data and Python objects
  • Built-in admin interface + authentication features
  • And much more! See feature overview

Ways to use Django

  • All-in-one MVT (model-view-template) app, which means that both the app logic and the HTML page construction happen on the server side, within Django. This doesn't allow page content to change after loading, unless you add Javascript over the top.
  • REST API backend only that performs app logic and returns JSON to a separate frontend app (ex, a Javascript framework like React or Angular). This is a more "modern" approach that allows content to change after page load.

In this class, we'll use the MVT approach

Django MVT

Django MVT

  • Model The data access layer. This layer contains everything about the data: how to access it, how to validate it, which behaviors it has, and the relationships between the data. Note that this layer is not required! Sometimes a request only generates a view, which populates a template.
  • View The logic layer. This layer contains the logic that accesses the model and populates the appropriate template.
  • Template The presentation layer. This layer defines how something should be displayed on a Web page .

Django MVT

Getting started with Django

Installing Django locally

Django in Replit

For our project, we'll run Django in Replit. From here on out, we'll follow this tutorial:

Python 2 Django tutorial

The tutorial will guide us through building a simple Django web app the displays the current weather based on the user's location.

Homework!

For next time, please make sure you've completed tutorial steps 1-3!

Also, please register for an OpenWeather API key! (step 1 in Configure OpenWeather API key)

Ex1