Codementor Events

Building an AJAX Helloworld with Python Pyramid

Published Apr 15, 2015Last updated Mar 21, 2017
Building an AJAX Helloworld with Python Pyramid

Introduction

In this tutorial I will take you through the process of making Ajax happen. If you would like a bit of an overview of what Ajax actually means before actually implementing it then check out this tutorial.

Ajax requires server side and client side code to play nice, this tutorial will cover both sides. On the server side we'll be using the Pyramid framework, and on the client side we'll be using JQuery. These tools are very robust and well-documented and have big friendly communities backing them up. This tutorial will not cover the nuts and bolts of the various technologies used. The techniques, tools and languages covered are not the only ones worth using. This is just a hello-world.

There is a complete working copy of the code I will be going through here.

Getting Started with Pyramid - Installation

Pyramid is a very light-weight web framework written in Python. We'll be using this for the server side of the our application. Don't worry if you are not familiar with Pyramid or even Python, the code I'll include here is dead simple.

To get started with Pyramid we'll first need to install it. First make sure you have Python installed then open up a terminal, navigate to the directory where you want to store this project and then type in the following:

virtualenv my_venv --no-site-packages

This will create a virtual environment. Starting new projects inside their own environments is generally good practice as it prevents certain kinds of package conflicts. If that doesn't make sense, don't worry too much. We'll just keep following good practice regardless.

The command we just executed created a directory called my_env and put a bunch of stuff in it. The next step is to activate the environment:

cd my_env
source bin/activate

This activates your virtual environment. To deactivate it just type in deactivate.

Now we install Pyramid into the environment with this command:

pip install pyramid

No errors? Good. That means you now have Pyramid installed in your virtual environment. If you can't get these steps to work then you can find in depth instructions on how to install Pyramid on various operating systems on the Pyramid website.

Your First Web Application

Once Pyramid is installed getting a basic web app up and running is pretty straight-forward. Type the following in your console:

pcreate -s starter hello_ajax

That command makes a basic application called hello_ajax. It makes use of the starter scaffold. Pyramid has created the skeleton of a web application for you, the application works but doesn't do a whole lot. Pyramid comes with a few different scaffolds and more can be downloaded. A scaffold is effectively a recipe for a web app. Using the starter scaffold, Pyramid creates something very basic, other scaffolds can be used to add other functionality. For example the alchemy scaffold adds database interaction to the mix. For more information on the available scaffolds and how to use them I will again refer you to the official Pyramid documentation.

The next step is to install your web app. Type the following into your console:

cd hello_ajax
python setup.py develop

This makes sure all the dependencies of the hello_ajax application are in place. Once that command finishes it is time to launch the application:

pserve development.ini --reload

This launches the development server and serves your app. You'll notice that at the bottom of the output there is an address, probably 0.0.0.0:6543. The 0.0.0.0 part is an ip address, it is the address of the localhost, the computer you are working on. The 6543 part is called a port number, this is a little hard to visualise for some people. If an ip address points to a house then the port number points to a specific door or window. If that doesn't make sense then don't worry too much. What matters is that if you open up a browser and put the address 0.0.0.0:6543 in the url bar then you will be greeted by a pretty welcome page with a message something like Welcome to hello_ajax, an application generated by the Pyramid Web Framework.

Well done! You have now created a working web application. The next step is to get it to display something other than a friendly welcome message.

Basic Application Structure

The pcreate command didn't do anything especially magical, it just created a directory structure and put a couple of files in it. The directory structure will look something like this (I've skipped some stuff on purpose, it's not all relevent for this tutorial):

\hello_ajax
      \hello_ajax        <-- this holds the actual application   
      development.ini    <-- settings file. We wont need to edit this
      setup.py           <-- python script used to install the app

We'll be working on files inside the hello_ajax application directory. In here you will see a couple of things:

\static      <-- stores all the css and js files our app uses.
\templates   <-- templates are 'rendered' to create html 
__init__.py  <--  is the initialisation script
tests.py     <-- unit tests. We wont be writing any
views.py     <-- view code

The templates directory contains templates that are rendered through use of a rendering engine. There are a lot of different rendering engines available, the starter scaffold uses Chameleon. We could switch it for a different one if we wanted but it's not necessary here. If that doesn't make much sense it should soon, you'll be writing your own template pretty soon.

View functions are called as a result of http requests being sent to the web application. They are just functions that are mapped to urls. They can be used to do some very clever things like database interactions, launching external processes, calculating pi to 100 places, whatever really. Pyramid takes whatever a view function returns and renders it with a renderer, the result of that is then packaged in an http response object and sent off to whoever sent the request to the url mapped to the view.

Now there are quite a lot of different kinds of renderers, the ones we will be working with are the Chameleon template rendering system and the json renderer.

Your First View

Open up views.py. You will see one function. A little something like:

@view_config(route_name='home', renderer='templates/mytemplate.pt')
def my_view(request):
    return {'project': 'hello_ajax'}

The application, as it stands, only has one view. Change it to say greetings ajax instead of hello_ajax' and save your changes. Then refresh the page you had open in your browser (0.0.0.0:6543`). Do you see that the welcome message changed?

The my_view view function makes use of the renderer templates/mytemplate.pt. Open it up in your favourite text editor. There is quite a lot in there that we just don't care about so delete all its contents. Now copy the following into the file and save it:

<!DOCTYPE html>
<html lang="${request.locale_name}">
  <head>
  </head>
  <body>
    <h1>${project}</h1>
    <button onclick="do_some_ajax()">Do some ajax</button>     
  </body>
</html>

Looks a lot like html, doesn't it?

Reload the page again and see what happens. You'll see something distinctly less pretty than what was generated by the scaffold. If you push the Do some ajax button nothing will happen.

Adding Static Resources

Open up the static directory in your project. You'll see a few things there. You can delete all of it if you want, we won't need it. Make a new file called hello_ajax.js and put in in the static directory. Open the file and put the following in it:

function do_some_ajax(){
    alert("TODO: implement ajax call");
}

Now edit templates/mytemplate.pt so it looks like this:

<!DOCTYPE html>
<html lang="${request.locale_name}">
  <head>
     <script type="text/javascript" src="${request.static_url('hello_ajax:static/hello_ajax.js')}"></script>
  </head>
  <body>
    <h1>${project}</h1>
    <button onclick="do_some_ajax()">Do some ajax</button>     
  </body>
</html>

Save everything and reload the page in your browser. Now click on the Do some ajax button. You will get an alert.

Take a look at this line:

<script type="text/javascript" src="${request.static_url('hello_ajax:static/hello_ajax.js')}"></script>

It rendered into a normal looking html, the src attribute was filled in by Chameleon by calling the function request.static_url('hello_ajax:static/hello_ajax.js'). That function returned a url by which the browser could access the hello_ajax.js file we just made. If that looks confusing then don't stress out. The point is that our app can serve static files.

Doing Ajax with JQuery

The next step is making the Ajax actually happen. This means that the client needs to be able to issue an ajax request and the server needs to be able to respond to it. Go to the JQuery website and download it. We'll be using version 1.11.2 but the code we'll write here will be compatible with all modern versions. Put the jQuery source inside your static directory. And add the relevant line to templates/mytemplate.pt.

<!DOCTYPE html>
<html lang="${request.locale_name}">
  <head>
     <script type="text/javascript" src="${request.static_url('hello_ajax:static/jquery-1.11.2.min.js')}"></script>
     <script type="text/javascript" src="${request.static_url('hello_ajax:static/hello_ajax.js')}"></script>
  </head>
  <body>
    <h1>${project}</h1>
    <button onclick="do_some_ajax()">Do some ajax</button>     
  </body>
</html>

If your directory structure looks like: static/a/b/c/jquery.js then your template will look like:

<!DOCTYPE html>
<html lang="${request.locale_name}">
  <head>
     <script type="text/javascript" src="${request.static_url('hello_ajax:static/a/b/c/jquery.js')}"></script>
     <script type="text/javascript" src="${request.static_url('hello_ajax:static/hello_ajax.js')}"></script>
  </head>
  <body>
    <h1>${project}</h1>
    <button onclick="do_some_ajax()">Do some ajax</button>     
  </body>
</html>

Simple eh?

Now we will use jQuery to issue an ajax request. Open up static/hello_ajax.js again and edit it to look like this:

function do_some_ajax(){
    jQuery.ajax({
        url     : 'ajax_view',
        type    : 'POST',
        dataType: 'json',
        success : function(data){
            alert("Success. Got the message:\n "+ data.message)
        }
    });
}

Save your changes and reload the page in the browser. Now when you click on the Do some ajax button... Nothing happens!

Enter Firebug (or equivelent)

Every modern browser either comes with developer tools built in or has them available as a plugin. I won't talk you through all of them because there are quite a lot of options. They all have fairly similar functionality though. Firebug is a Firefox add-on and will be the tool I'll stick to in this explanation. To install it using Firefox, go to tools > add-ons and install firebug. Once it is installed you may need to restart your browser.

Now, navigate to 0.0.0.0:6543 and press F12. This will open up a little thing at the bottom of the page. Click on console and if you see a button that says enable console or something similar then click on it and reload the page. Now click on our Do some ajax button. You should see a little red message in the firebug console that says something along the lines of POST http://0.0.0.0:6543/ajax_view 404 not found.

That means that the client code that we wrote created an ajax request and sent it to the url we mentioned. But that url does not exist because we haven't made it yet. Time to make the server side part.

Your Second View and the Json Renderer

To complete the ajax functionality we will need to implement the server side of the ajax conversation as well. This means we will need to make a view function that returns the data we want, and we will need to let Pyramid know what url should map to that function.

Open up __init__.py. Most of it won't make any sense.

There will be a line in there somewhere that says config.add_route('home', '/'). What that means is, if someone accesses the root url 0.0.0.0:6543/, then use the view function with the route name home. We will add a line under that that looks like this:

    config.add_route('generate_ajax_data', '/ajax_view')

You guessed it, this line makes a view named generate_ajax_data available at the url 0.0.0.0:6543/ajax_view. Save your changes.

The next step is to make the actual view. Let's look again at views.py. This is the one already implemented view.

@view_config(route_name='home', renderer='templates/mytemplate.pt')         #1
def my_view(request):                                                       #2
    return {'project': 'greetings ajax'}                                    #3

The view function itself is defined in lines 2 and 3. A view function takes a request as a parameter and outputs a dictionary with some data. Going into the details of all the stuff you can do with a request object is way beyond the scope of this tutorial so don't worry about it for now. Line 1 decorates the my_view function in order to tell Pyramid that my_view is to be given the route name home and gives it a renderer that is a template.

Add this code to views.py:

@view_config(route_name='generate_ajax_data', renderer='json')                     #1
def my_ajax_view(request):                                                         #2
    return {'message': "yo mamma's so classless she could be a marxist utopia"}    #3

Line 1 says our view will have the route name generate_ajax_data and will be rendered as json. Lines 2 and 3 are the actual view function. Save your changes and refresh the page in your browser. Make sure firebug is open then click the Do some ajax button. There are a few things worth noticing here: firstly the alert box that comes up. Recognise it? The message inside it was returned by our view function. Looking again at our JavaScript code:

function do_some_ajax(){
    jQuery.ajax({
        url     : 'ajax_view',
        type    : 'POST',
        dataType: 'json',
        success : function(data){                                     //***
            alert("Success. Got the message:\n "+ data.message)       //***
        }                                                             //***
    });
}

The starred lines are the ones that actually made the alert box happen. The optional success parameter of the JQuery ajax call takes a function, we gave it an anonymous function which just makes an alert.

The next thing worth noticing is that there is no new error message in the firebug console. The ajax call is still noted but it is no longer in red.

Conclusion

We have covered quite a lot of ground in this tutorial. We have installed Pyramid in its own virtual environment, created a basic application using a scaffold, made our own Chameleon template, and added enough JavaScript and Python machinery to make a basic ajax call happen. Pat yourself on the back. Now, what's next?

If you still aren't sure about the basic mechanisms that Ajax is based on then I would suggest looking at CodeMentor's introductory material. If you are happy with this and want to learn more about the client-side of things I would suggest checking out the JQuery documentation. If you don't like Pyramid then there are loads of different frameworks and server side technologies to choose from.

Discover and read more posts from Sheena
get started
post commentsBe the first to share your opinion
Scott Cunningham
6 years ago

Thank you for this quality tutorial, this made jumping into Pyramid very easy.

3daygoaty
7 years ago

Hi there, this is a very friendly tutorial and I found no others like it!

However, I only get so far as the web page is not instantiating the server-side content and the server gives a 404 for the .js file.

I am using ubuntu and python 2.7 nd followed all steps you provided.
I saw some errors when I run the setup command. For example

File “build/bdist.linux-i686/egg/jinja2/asyncfilters.py”, line 7
async def auto_to_seq(value):
^
SyntaxError: invalid syntax

There are other errors associated with jinja2. I also notice the template files in the tute don’t end with .pt but with .jinja2.

The http server error is this

Serving on http://localhost:6543
2017-07-24 12:55:45,725 ERROR [pyramid_debugtoolbar:257][waitress] Squashed Exception at http://localhost:6543/${request.static_url(‘hello_ajax:static/hello_ajax.js’)}
traceback url: http://localhost:6543/_debug_toolbar/33303237343033343034/exception
Traceback (most recent call last):
File “/home/threedaygoaty/Desktop/my_ajax3/local/lib/python2.7/site-packages/pyramid/tweens.py”, line 39, in excview_tween
response = handler(request)
File “/home/threedaygoaty/Desktop/my_ajax3/local/lib/python2.7/site-packages/pyramid/router.py”, line 173, in handle_request
raise HTTPNotFound(msg)
HTTPNotFound: /${request.static_url(‘hello_ajax:static/hello_ajax.js’)}

I tried installing async separately then force reinstalled jinja2. No errors. Then I re-ran setup.py develop again, and go no errors but the problem persists.

Can you please tell me what to try?
Best
Craig

3daygoaty
7 years ago

Okay the issue is that Chameleon has been replaced by ninja2, a different template engine which has a different syntax. I get the above working by replacing
${command} with {{command}}

muhammad nur
7 years ago

may you help me please, already replacing the command but still not working
help me please

Edson J Bueno
8 years ago

view_config not define …

Show more replies