This is an example of a full web-based application written entirely in Python using modules that the author has developed over the years.
- [Instructor] This is an example from my own toolbox. This is a short URL application that I use for my own website. For example, if I open a new tab here and I type in j.bw.org, which is my short URL server, and just LDC, this will take me to a particular page in my site which I use for my Lynda.com landing page. And so here I've got a copy of this database system running on a local server on this demo machine, so this is not the one that's running on my live server, so we can play with it a little bit.
This page here is the back end database of the system. From this webpage I can add, edit, test and delete URLs. This code runs on a web server. So we won't be testing it in Komodo. This is running on a local server here on this Mac that I'm recording on. And it's important to understand that there's a lot of moving pieces for any web application. To implement this, it takes some knowledge of the web server, in this case it's an Apache web server. It takes knowledge of, obviously, the language that you're writing scripts in, in this case Python.
Also your database system, in this case I'm using SQL, and some knowledge of HTML and CSS. And so there's a whole lot of moving pieces here, and they all have to work together in order to make this work. And so for example if I want to add a new entry here, I can put in the home page of my website. And I can put in a short token, for example I want bw in this case, and when I click add record, it's now added that to the database.
And we can edit that, we can bring it up, we can change that if we want to. We cannot change the short URL because that's used as a key. And if we want to we can delete a record. So I can delete this one if I want to, and confirm delete. I can also test them. You'll notice when I hover my cursor over this, I don't know how well you can see it on your screen, but down at the bottom there it says localhost/jurl/ldc. And so when I click on that, it redirects to the appropriate website, and this is using an HTTP redirect.
And again that's another moving piece. Some understanding for this application of the HTTP protocol. So like I said there's a lot of moving pieces and there are a lot of parts to this, we're just going to go over it really quickly in the time that we have allotted for this lesson. I'm going to switch now to Komodo Edit, and the first thing we're going to look at here is my working copy of jurl.py. And so all of these files are in the jurl subdirectory under chapter 15, and this is the entire system, this is everything that you need to run this on your web server with the exception of, however, you need to configure your web server in order to be able to run Python scripts.
And whatever configuration you need to be able to run the types of redirects we're doing. So in this case, for Apache, and I've included this file, although this is almost certainly not exactly what you need even in your Apache server. So you won't be able to just drop this in and have it work. Unfortunately, configuring a web server is a very individual thing, and every web server is configured differently. So this almost certainly will not work when it's directly dropped in there, but it gives you an idea of what's needed to make this work on this Mac.
This is not even the one from my web server. This is the one for this local testing environment. And the important thing to see here is the rewrite engine, which allows me to rewrite the URLs. And that allows me to use something like this URL that you see here, where it just says local host, jurl and the token. And this rewrite gets that passed as a proper CGI query. So like I said there's a lot of moving pieces here to make this work.
But the script itself is fairly simple. This is the redirect script, and you'll notice it's just 60 lines of code. And that's with spaces and comments and everything. It's probably less than 50 lines of actual script. A number of libraries involved here, and I've given you copies of all these libraries, these are all libraries that I've written myself, modules that I've written myself. One to handle CGI, the database one that we've already talked about, and one for operating with configuration files.
I want to take just a moment and talk about why I write these separate modules. Because there are publicly available modules to do what these modules do, and you can certainly use them if you like. In my view, many of the publicly available modules have features that I don't use, that increase the complexity and reduce the efficiency of the code. I prefer simple and functional. And I don't mind creating them myself, in fact I enjoy the process. I do this because I enjoy it. And I usually learn from the process.
So I strongly recommend that you write your own modules for many of these tasks. You and your code will benefit from the exercise. So I've got one here for CGI, and that's interfaced with the CGI protocol which you need for most web applications. Of course the database one you've seen already. And the one for working with configuration files. This is a technique that I often use in many languages, and I find this very useful. I'll create a global, in this case a dictionary structure, but some sort of a global structure, most languages have some sort of a hashed key value structure that works well for this.
In Python it's dictionaries. And this allows me to create some global variables without stomping on the global name space. And I'll usually name it G. It's just a way that I've learned over the years that this works very well. Also it's easily portable when I take a script and I rewrite it in another language. So the first thing that we do here for main is we call init. And so I'm going to scroll down here and show you init. Init sets up, basically, our global variables.
Sets up the CGI environment. Reads the configuration file, and initializes the database. So that's all very straightforward. Here in main, we're reading various path variables and system arguments, we're basically setting up our environment reading however it is that the information is getting passed to the script, and I make it possible to do it in a number of different ways. And then, the real meat of it starts down here on line 40, where we look up a short URL in the database.
And again, I'm using my SQL query value. This particular script doesn't use a lot of SQL, so I find it really simple to just type the query there. And you'll notice that I'm using the exception system for handling possible errors. Down here on line 46, this is where the redirect happens. And basically sending a status 302, which is an HTTP status for a redirect, along with the location.
And that is it. This is a very simple script, the rest is just error checking and processing, this is a very very simple script. This does the actual redirect. The more work is done in the back end system, db.py, this is the script that we saw here in Chrome. This has a lot more moving parts. This is the database management interface. And again, I'm using a lot of my own modules. Hashlive is one that comes with Python, but there's my CGI module, my DB module, and one for template processing, to make the HTML easier.
So you'll notice that there's an HTML directory here, and there's a bunch of these little HTML files, I'll open one, and these have these variables in them, and this is my own templating system. Again, there's a templating system that comes with Python and you're welcome to use it. I just find it large and cumbersome, and writing my own was an interesting exercise, and I like using it, it's written the way that I like to use it. So, if we come back here to DB, you see I have again my global variable, and I find that very convenient.
There's an init. I try to do things in the same way, so I'll always have a main, and then init function, and this just helps me to be able to navigate my own scripts if I come back to something years later. And I've been using these techniques for many years so I find this very convenient. So, we set up CGI, we send a header, we do all of these things to set up the environment for the script. Now this dispatch function, this is an interesting bit of work.
This is where a lot of the work of the script happens. So, when you're navigating from one web page to another web page, because HTTP is stateless, it's really difficult to kind of keep track of where you are. So I deposit little breadcrumbs in the pages, in the form of hidden CGI variables. These are variables using the hidden attribute, they exist in the CGI domain, and yet they're not visible on the page. And so I use those little breadcrumbs to navigate around. And every time the script enters, it has no state, but it gathers its state from those breadcrumbs, and then this dispatch serves as a jump table to tell it which page to display.
Down here we have listrecs. This is the code that does this on the screen, which will list the records. And you notice there's little arrows, we don't have enough records in here, but if there was more than a certain number of records it will page, it will put them on separate pages to make it easy to navigate. And so all of that is done in here. And beginning on line 177, we have our database navigation actions. We have one for adding records, we have one for editing records, deleting, confirming deletes, updates, and all of this uses my database interface, which makes the database part of this really easy, and allows me to focus on the logistics of the actual code.
The rest of the code in this file is about managing the templates and the HTML. I know this has been a lot, and I hope this helps you to see how simple and powerful Python can be, in this sort of environment. Of course there are a lot of other working, moving parts. There's the HTML, the CSS, managing the web server, understanding the database. There are all of these other parts, and with a little knowledge about these parts, Python allows you to create simple and powerful database applications.
- Python anatomy
- Types and values
- Conditionals and operators
- Building loops
- Defining functions
- Python data structures: lists, tuples, sets, and more
- Creating classes
- Handling exceptions
- Working with strings
- File input/output (I/O)
- Creating modules
- Integrating a database with Python db-api