Introduction to the Python Pyramid Framework

Introduction

In this tutorial, we're going to learn how to use the Pyramid framework in Python. It is an open source web development framework which uses the Model-View-Controller (MVC) architecture pattern and is based on Web Server Gateway Interface (WSGI). The Pyramid framework has a lot of useful add-on packages that make web development a lot more convenient. Some other popular alternatives for web development in Python include Django and Flask.

Prerequisites

You need to have basic knowledge of HTML for this tutorial. If you do not have any prior experience with it, do not worry about it, you can still follow this tutorial and understand how Pyramid works, but to develop real world web applications you will have to go back and learn HTML.

Architecture

Before we move on and see the code, let's first understand WSGI and MVC.

WSGI is basically a standard which defines the way in which a Python based web application interacts with a server. It governs the process of sending requests to a server, and receiving responses from a server.

MVC is an architectural pattern which modularizes your application; the model contains the data and business logic of your application, the view displays the relevant information to the user, and the controller is responsible for the interaction between the model and the view.

Google Maps is a perfect example of the MVC architecture. When we use the route-finding feature in Google Maps, the model contains the code for the algorithm which finds the shortest path from location A to location B, the view is the screen that is shown to you containing the map labeled with the route, and the controller contains the code that uses the shortest path found by the model and displays it to the user through the view. You can also view controller, as the code which receives a request from the view (by the user), forwards it to the model to generate a response, and then displays the response from the model back to the user through a view.

Besides WSGI and MVC, there are two more terms that you should be familiar with, which are "routes" and "scripts". Routes allow your website to be divided into different webpages, with each webpage performing a different function.

Let's consider Facebook as an example. If you wish to view your messages, a new webpage with a different view is opened up for that, if you wish to view your own profile, a new webpage is opened for that, but they are all connected to your main website. That's done through routes. Each time you click on a button or link, you are redirected to a new webpage as specified by the routes in our application.

As for scripts, they simply include configuration settings for our application, and help in managing it.

We will learn more about all these terms when we create a basic web application using Pyramid. So, let's begin.

Installation

Whenever we develop a web application that is to be deployed online, it is always considered a good practice to make a virtual environment first. The virtual environment contains all the libraries, or frameworks and all the other dependencies that are necessary for running the web app. This way, when you deploy your app to a server, you can simply re-install all those libraries on the server, for your application to run smoothly.

Let's create a virtual environment before we move forward. Install virtual environment module by running the command below in your terminal:

$ pip install virtualenv

To test that your installation was successful, run the following command:

$ virtualenv --version

If you see a version number printed to the console then the installation was successful (or virtualenv was already installed on your system).

To create a virtual environment, first navigate to the folder where you wish to create it, and then run the following command:

$ virtualenv myvenv

Note: You can name your virtual environment anything you want. Here we're using "myenv" for demonstration purposes only.

The last step is to activate your virtual environment. On Mac, run the following command in the terminal:

$ source myvenv/bin/activate

On a Windows machine, you can activate the environment with the following command:

'Installation folder'\myvenv\Scripts\activate.bat

Now that you have your virtual environment set up, let's install Pyramid in it. We will use the pip package manager for that:

$ pip install pyramid

Note: When you are done with working with the application and wish to deactivate your virtual environment, run the following command in the terminal:

$ deactivate

Coding Exercise

In this section, we will start off by coding a skeleton app to understand how the Pyramid apps are structured and how they communicate at a basic level. After that, we will see how to create applications with multiple views.

A Simple Example of Python Pyramid

# intro.py
# Import necessary functions to run our web app

from wsgiref.simple_server import make_server
from pyramid.config import Configurator
from pyramid.response import Response

# This function receives a request from the user, and returns a response
def intro(request):
    return Response('Hi, My name is Junaid Khalid')

# This function will start a server on our computer (localhost), define the
# routes for our application, and also add a view to be shown to the user
def main():
    with Configurator() as config:

        config.add_route('intro', '/')
        config.add_view(intro, route_name='intro')
        application = config.make_wsgi_app()

    # 8000 is the port number through which the requests of our app will be served
    server = make_server('0.0.0.0', 8000, application)
    server.serve_forever()

main()

Note: The Configurator module is being used to connect a particular view to a specific route. For instance, on Facebook, the "My Profile" view would be different than the "News Feed" view, and they both have different URLs as well. This is exactly what a configurator does; connecting a specific URL/route to a particular view.

Then make_server methods is used to run our application on a local HTTP server on our machine, with an assigned port number.

The intro function is used to process the requests received from the user, process them, and return the response to the view. Any processing of the request before sending a response, can be done inside this function.

To run the above application on your workstation, go to the terminal and run the .py file we just created:

$ python3 intro.py

In my case, the filename is intro.py, but yours could be different depending on what you decided to name it.

Then open any web browser on your PC, and go to this address: http://localhost:8000. You should see a webpage with "Hi, My name is Junaid Khalid" written in a very aesthetically displeasing way. To make it look more pleasant, you can return HTML code as a response as well. For a simple example, let's edit intro function:

def intro(request):
    return Response('<h2 style="text-align: center; font-family: verdana; color: blue;">Hi, My name is Junaid Khalid.</h2>')

Replace the intro function with the one above, and see the output now. A lot better, right? This was just an example. You can make it a lot better.

Note: When you make any change in the code, the server is not automatically going to log that. You will have to stop the server, and then restart it to see your changes take effect. To do that, open your terminal where the server is running and press Control+C, this will terminate the server. Then you can restart your server as usual to see the changes.

Separating and Displaying Multiple Views

In this section, we will add a few more views as well as remove our views from the main file (i.e. 'intro.py' file), and put them all in a new separate file ('all_views.py'). This will modularize our code, make it look cleaner, and will also allow us to add new views more easily. So, let's do it.

# all_views.py
# Import necessary functions to run our web app
from pyramid.compat import escape
from pyramid.response import Response
from pyramid.view import view_config

# view_config functions tells Pyramid which route's view is going to be defined in the function that follows
# the name of the function does not matter, you can name it whatever you like

@view_config(route_name='intro')
def home_page(request):
    header = '<h2 style="text-align: center;">Home Page</h2>'
    body = '<br><br><p style="text-align: center; font-family: verdana; color: blue;">Hi, My name is Junaid Khalid.</p>'
    body += '<p style="text-align: center; font-family: verdana;"> This is my portfolio website.</p>'
    footer = '<p style="text-align: center; font-family: verdana;">Checkout my <a href="/jobs">previous jobs</a>.</p>'

    # In the 'a' tag, notice that the href contains '/jobs', this route will be defined in the intro.py file
    # It is simply telling the view to navigate to that route, and run whatever code is in that view

    return Response(header + body + footer)

@view_config(route_name='jobs')
def job_history(request):
    header = '<h2 style="text-align: center;">Job History</h2>'
    job1 = '<p style="text-align: center; font-family: verdana;">Jr. Software Developer at XYZ</p>'

    return Response(header + job1)

Note: At the beginner level, you can write the HTML code by following the strategy used above i.e. declare tags in different variables and simply concatenate them when sending back the response. At some point you'll likely want to use a templating engine, like Jinja to make HTML generation much simpler.

Our application won't run just yet, we need to edit the intro.py file as well.

# intro.py
# Import necessary functions to run our web app

from wsgiref.simple_server import make_server
from pyramid.config import Configurator
from pyramid.response import Response

def main():
    with Configurator() as config:
        # In add_route function, the first parameter defines the name of the route
        # and the second parameter defines the 'route' or the page location
        config.add_route('intro', '/')
        config.add_route('jobs', '/jobs')

        # The scan function scans our project directory for a file named all_views.py
        # and connects the routes we provided above with their relevant views
        config.scan('all_views')

        application = config.make_wsgi_app()

    # The following lines of code configure and start a server which hosts our
    # website locally (i.e. on our computer)
    server = make_server('0.0.0.0', 8000, application)
    server.serve_forever()

main()

As you can see, we have removed the code for our previous view. If we had declared all these views in a single file, the file would have looked a lot more cluttered. Both files look very clean now, and each file now serves a single purpose. Let's see what our web app looks like right now.

Output:

In the image above, we can see our home page. It is located at the route 'http://localhost:8000'. It does not look very aesthetically pleasing, but as stated at the start of the tutorial, this was not our aim anyways. If we want to make it look aesthetic, we can add a lot of styling to it using HTML style attribute, or CSS, or use templates from Bootstrap.

Moving on, you can also see a hyperlink which has been named 'previous jobs'. Clicking that would take you to a new webpage with a different route. We will see the output of that in the next image.

Output:

The above image shows our Jobs page. It is located at the route http://localhost:8000/jobs. We specified this route in our 'intro.py' file. I have only added one job to show as an example.

Conclusion

Pyramid is a Python based Web Development Framework to build web apps with ease. In this tutorial, we learned how to install Pyramid inside a virtual environment and make a basic Web Application using Pyramid which runs on a locally created server on our computer.

If you would like to go into more details, visit Pyramid's documentation - it is quite elaborate and beginner friendly.