Wednesday, May 15, 2013

Web.by Web.py 1: Tutorial

Yesterday, we created our first python program, a simple terminal "to do" list, today we are working with the web. In this example (spanning across two days), we will use the Apache Web Server and either the Postgres or MariaDB database manager. Click any of the above links to refer back to those posts in SoC. That being said, I will be working off of this tutorial (simply because it is the easiest one I found). If you have any questions, they might be answered on that page. Now, let's get to Web.py!

First things first, why web.py? Web.py is simple and extensible. As a developer, you can do many things with it that might be more difficult in other frameworks. At the same time, due to it's simple code base, it might be a little more difficult to use and set up. For that reason, it is a perfect candidate to cover first when working with web frameworks. Later, I might cover Django and some other web languages (such as PERL or PHP), if there is enough support.

To get started, make sure you have started your Apache (httpd) server and database manager's (either mysqld or postresql) daemon. Also make sure webpy is installed. Once done, we can begin working with our first web.py code. If you remember, at the head of most python code, there is a section to import important modules. In this case, in order to use web.py, we must import the "web" module:

import web

Once this is done, we must set up our urls using typical python fashion:

urls = (
  '/', 'index'
)

Note that "urls" comes from the "web" module. Here we are setting up a simple url structure with an open primary directory ('/') and sing input class ('index'). In principle, we could name this class whatever we like, so long as we define it appropriately later:

class index:
    def GET(self):
        return "Hello world!"


In this example, we are defining the class index to use the "GET" function, with the "(self)" tag essentially defining the function to be self-consistent without any extraneous variables. The GET function has been seen previously in SoC, and is essentially a function to display information. Remember that the POST function is the opposite of this and allows us to indirectly modify our database.

Before running this code, we must set up the url structure so that web.py can understand what we are doing. In this case, we must add the following lines:

if __name__ == "__main__": 
    app = web.application(urls, globals())
    app.run()        

These lines are essentially claiming that if we are on the mian page, the web application should run. We define "app" to run the application function within the web module and call a basic url structure and global calls for later use. We then run the app with "app.run."

To reiterate, the code should look like this:

import web

urls = (
    '/', 'index'
)

class index:
    def GET(self):
        return "Hello world!"

if __name__ == "__main__":
    app = web.application(urls, globals())
    app.run()

Let's save this as "code.py" and run it like so:

$ python code.py

So long as your database manager is working appropriately, you should see a simple "Hello world!" message displayed when going to the linked site in any browser. Which is great! That means you are officially on your way to working with your own web server and site. If you want to choose which port (rather than the standard 8080), you can do the following:

$ python code.py 1234

Substituting "1234" with whatever numbers you like. Note that you might need to specify the use of python2 over python3. If that is the case, simply use this command:

$ python2 code.py


Now, let's work on some templating with HTML. First things fist, make a new directory called "templates," in this folder, create a file called "index.html." In this file, you can write any html code you want, but for now, let's just keep it simple:

<em>Hello</em> world!

To call this file we need to go back to our code.py file and add in 


render = web.template.render('templates/')

Under the first line. This calls the render function in the template function in the web module, which depends on a directory of your choice. In this case, that directory is "templates." The "render" function is essentially a python call for the data inside the file.

We then have to modify our index.GET function to allow access to the file we just created. By substituting in the following line:

        return render.index()

In the end, the code should look like this:

import web
render = web.template.render('templates/')

urls = (
    '/', 'index'
)

class index:
    def GET(self):
        return render.index()

if __name__ == "__main__":
    app = web.application(urls, globals())
    app.run()

When you run the code and visit the link in your web browser, you should see "Hello world!" But, let's say you want to have your site say hello to one person in particular. You could change the contents of templates/index.html to:

$def with (name)

$if name:
    I just wanted to say <em>hello</em> to $name.
$else:
    <em>Hello</em> world!

In this case, you are using a mixture of python and html code, but because the index.html file is naturally html, you have "commented out" the python code with the "$" sign. In this file, you are assuming that the variable "name" has been defined in code.py, and defining this file with that variable. You are then giving a simple if, else statement. If the site is visited with the variable "name" specified, the text will display, "I just wanted to say Hello to [name]." Otherwise, it will read exactly what it did last time.

To get this to work, we must change our code.py file in a few ways. First, we must make the index.GET funtion a function of "name." second, we must imput a name. In order to do this, we must modify the index class to read:

class index:
    def GET(name):
        i = web.input(name=None)
        return render.index(i.name)

The line "i = web.input(name=None)" means that we are defining a new class "i" with contents determined by the browser url. If you run the code and visit the url at /?name=Joe, then the site will say hello to Joe.To simplify this url a little, we might want to change the url line at the top to read: And change the index.GET function to be a function of both "self" and "name," like so: Once done, your code should look like this: 

'/(.*)', 'index'

And change the index.GET function to be a function of both "self" and "name," like so:

def GET(self, name):

Once done, your code should look like this: 

import web
render = web.template.render('templates/')

urls = (
    '/(.*)', 'index'
)

class index:
    def GET(self, name):
        i = web.input(name=None)
        return render.index(i.name)

if __name__ == "__main__":
    app = web.application(urls, globals())
    app.run()

If you run the code, your site should read "Hello world!" initially, but when visited from the /Joe url, it will say hello to Joe. Tomorrow, we will work directly with databasing, wich can be somewhat challenging.

As always, thanks for reading.
-Leios

No comments:

Post a Comment