hola a todos, thanks everyone for coming. my name is jose nazario and i'm goin gto be talking about building web applications in python using some simple components. you can find the slides on my website at http://monkey.org/~jose/presentations/umeet05/slides/ ... [slide 1] here's a brief overview of the talk. i'm going to introduce the two main paradigms of this talk, web app frameworks and the MVC model of programming, in the next few slides. i'll then focus on the actual python frameworks we're using in this demo and how they fit together to form a working application. and finally i'll be sharing the code i wrote as the demos, aka "bloggy", a simple blogging system. [slide 2] web app frameworks are just that, pieces of code that let you write your functional web app veyr quickly. they contain a number of pieces that let you get right to it. this can include "boilerplate" code, or code that you'd write every time for almost every app. you can write web applications in a framework like the ones i'll be introducing, or you can write you own using pre-existing components. we're going to mix these two, using the CherryPy web handler framework and some components to extend its functionality. the important thing about any framework is that it typically lets you get right to the very important bits of your application quickly. they handle the heavy lifting of handling user requests and such, letting you focus on getting your specific needs met. i've been using the frameworks described here (CherryPy, SQLObject, and even Django) at work and in some applicatins i've been writing outside of work, as well. i've found them to be feature filled and useful for getting my job done quickly. one of the things i wrote this week was a simple, lightweight interface to our vulnerability and malware writeup database. took me about 2 hours and was done in under a few hundred lines of code when it was complete. [slide 3] the main paradigm we're using here is the Model-View-Controll design. we're going to clearly split the requirements of our application across these boundaries, making it easy to manage the code. the model refers to the data model, in this case an SQL-backed app. you can use any back end, including flat files or directories, but the idea is the same. you make this a clearly managed piece of code and you can change it as needed. the view handles how the user will see the data presented to them, such as blog posts or customer entries. and finally the controller is the piece of the app that mediates this interaction, including reading and writing. [slide 4] slides: http://monkey.org/~jose/presentations/umeet05/slides/ the benefits of this modular stack that we have here - CherryPy, CherryTemplate, SQLObject and FormEncode - is that by having modular code, we can separate our use of these components and speed up development. we can extend it easily, especially in an object oriented language like python, where we can inherit the classes to extend them. the nice thing about these modules is that they're flexible, meaning we can use them for a variety of purposes. also, they leave the grunt work - handling web browser requests, writing SQL queries - to the module, and we get a simple interface. if you've ever programmed in PHP or a CGI-BIN application language like Perl, compare the code here to what you had to do before. you'll see that it's easier, and much easier to maintain. PHP, which i've done a lot of work in for myself, suffers from mixing all of this without the use of some newer packages. almost any CGI-BIN app will have to print out the HTML itself, making it a pain to manage the actual logic within that mess. simply put, i can't go back, and i hope you see the benefits here, too. [slide 5] our demo app is "bloggy" a dead simple codebase that you can take with you to explore and play with. it's a simple blogging system, not suitable for real world use, but it illustrates these ideas cleanly, i hope. you can create posts and browse them easily. if you want to extend it, go for it. you'd probably do much the same if you wrote a full featured blogging system you'd probably do somethin like this at the core of the app. anyhow, we'll be using this code in the next few slides. the code is here: http://monkey.org/~jose/presentations/umeet05/ i wrote it using Postgres on OS X, but it's highly retargetable to any supported DB and and platform supported by python. [slide 6] this is the simple view of the bloggy index, so posts by title and date. nothing fancy, and clearly i'm no guru of web design. i leave the sytles to someone else. [slide 7] here's a specific post, you can see how you can essentially drill into a post from that index page. pretty simple, eh? and just like you'd do if you were browsing a full featured and mature blogging system. [slide 8] slides: http://monkey.org/~jose/presentations/umeet05/slides/ first up, the main component here, CherryPy. this is a simple web app framework, handling requests and mapping them to the code. in CherryPy (or CP), web directories are under the "root" object as their own objects, and pages and vews are methods of those objects. this is the CherryPy website: http://www.cherrypy.org/ this will be more clean when i show you some code in the next few slides, but think about it this way: it's a simple, intuitive way to map requests to your code to handle it. CP handles the request and maps the arguments given to it (in the GET or POST methods) to the code for you to handle. one major drawback of CP is that it wont run as a CGI, so some hosting providers wont be available to host your app. it works best behind apache and ProxyPass. [slide 9] over the next two slides, you'll see the actual code from CP that creates a simple standalone web application. we have our SQLObject imports (and our model, which we'll explain later), but the key thing here is the root class. the __init__() method handles the database connection in our case. but on the next slide, we can see the main page and the app setup. [slide 10] the index method is the base directory, "/", of the web app. when we go to 10.10.10.11 (my IP in this case) as http://10.10.10.11:8080/ we get this method called. notice "index.exposed = True", this attribute says that the CP server can expose this to web clients. if you had a method under the Root object that wasn't supposed to be exposed, set this to False. the main() function starts it up. the configuration tells the server how to behave: Ocho:~/python/bloggy jose$ cat simple.conf [global] server.socketPort = 8080 server.logToScreen = True server.socketHost = '0.0.0.0' we listen for any requests coming in on port 8080 and log to the screen, useful for dev/testing work. [slide 11] this rehashes some of what i said in the previous slides, but you get the idea. mapping requests and arguments to code in a simple fashion. arguments can be passed in as a named argument in a GET request (or a POST request), like this: def index(self, q): ... to handle http://10.10.10.11/q=test or you can handle them as a dictionary with lots of pieces and take it apart inside your code. [slide 12] slides: http://monkey.org/~jose/presentations/umeet05/slides/ to complement this, we use CherryTemplate to create dynamic web pages. we embed python in the pages and it gets evaluated. link: http://cherrytemplate.python-hosting.com/ CherryTemplate (or CT) has access to the variants in the scope where the method renderTemplate() is called. we get some nice stuff in CT, including iterators, conditional expressions, and variable reference. as in any good MVC app, leave the logic of the controller inside the app and leave only the bits needed for the view in the template. [slide 13] here's an example template from bloggy, see how the CT specific bits are highlighted in red. you can wrap any HTML around this, including CSS or javascript. very easy to use! here we loop over the posts and print the link to the post by ID and list the title and the date. again, i think this is pretty easy and illustrates a powerful web app design technique. nothing too complicated here, and that's good! [slide 14] to render a template, CherryPy actually returns the generated string. we use renderTemplate from CherryTemplate to go over the HTML template and fill it out. we call them as files in this case, but we could have used a static string if we wanted. the key thing here is that by making it files, we split up the maintenance of this and make it easy to find what matters to us. if you have web designers, they can work on the layout and markup and you can keep working on the logic. [slide 15] here's a few more templating languages: kid, which is very powerful as well, but i didn't like the syntax. CheetahTemplate, which i think predates CherryTemplate, and is a lot like Python server pages. Myghty, which is inspired by the Perl HTML::Mason framework but lacks very good beginner docs. and Python Server Pages, which are very powerful but complicated. i like CherryTemplate: it's easy to use, powerful, and not complicated. [slide 16] slides: http://monkey.org/~jose/presentations/umeet05/slides/ SQLObject is our big, heavy lifter here. if you've written a lot of SQL, you know it can be a pain to manage. instead, we use an object-relation mapper like SQLObject to do that heavy lifting for us. we can interface to most popular databases and change that on the fly with little, if any, work involved. it also uses native Python data types, and lets us do everything we want from our database: selects, joins, updates, and even table management. [slide 17] here's Bloggy's simple model. we have a table, BlogPost, that has three columns: a post title, a body, and a date. SQLObject now uses this for everything to access and manage that table and the rows within it. we map the types to SQLObject column types, so it knows what to expect from them and how to deliver data to them. very easy! [slide 18] to create the table, i usually make a simple script like this initialization script. i create the tables as needed and voila, SQLObject has done the work for me. deleting tables is also easy, and is also managed using SQLObject. (ie TableName.deleteTable()) [slide 19] here are the results of our createTable() calls as viewed in Postgres. we can see tat it creates two things implicitely. first is an "id" column, which is the primary key of the table. the second is the table for the index on that table. we can make more indices if we want, and add constraints easily. [slide 20] slides: http://monkey.org/~jose/presentations/umeet05/slides/ SQLObject link: http://sqlobject.org/ some more, unrelated examples, showing how to cross reference tables using a foreign key, and how to make database indices, even with the UNIQUE constraint! all very easy, thanks to SQLObject. [slide 21] with SQLObject, adding data is very easy. you just call the class and fill out the fields appropriately. it will create the database row for you, or it will bump up an exception if something has failed. to access the data you can select using any requirements you want. for example, model.Mytable.select(model.Mytable.q.id == 1) would get the row where "id = 1". this returns a list of results. finally, to update, we can just access the feature we have and reassign the attribute: m = model.Mytable.select(model.Mytable.q.id == 1)[0] m.title = "This is my new title" and voila, it's updated. [slide 22] finally, FormEncode, which lets us enforce the data mode using validators. these validators operate on user-supplied data (from an HTML form) and help us ensure that the data maintains its integrity. what's nice about FormEncode is that we can do this efficiently, in a few lines of code, and bubble up errors to the user cleanly. what's even nicer is that it maps stuff to a format usable by SQLObject, which are just native Python data types. link: http://formencode.org/ [slide 23] the schemas used by FormEncode are a lot like the models used by SQLObject. we can allow extra fields in the form, which is handy if you have a form that will input into multiple tables and schemas, and you can filter them per-schema. the validators are almost like the types in SQLObject, and you can enforce any criteria you want on the input stream. you can also write your own validators, if you want to enfoce a format of the data. [slide 24] slides: http://monkey.org/~jose/presentations/umeet05/slides/ this is a modified CherryTemplate file showing you the places we bubble up the errors to the user. once rendered by the error form, they get wrapped in a CSS class that lets us change the color to red, for example (to make it highly visible). again, very easy. [slide 25] this is how we use FormEncode in our controller code. we basically run the form through the validator using htmlform.HTMLForm() and then look for any errors after we call the "validate" method on the resluting HTMLForm object. if we get any errors, we bubble up an error form (shown on the next slide) to the user. if not, everything must be ok, so we pass it on to the database for finally inserting it. voila, we have a new entry in our blog! [slide 26] again, a rehash of what was just said. we get user input in, we compare it against our scheme using validators, and if we have any errors, tell the user to try again. if not, we accept the data. very easy to do, an it only adds a few lines of code. [slide 27] this shows you how it looks to the user if an error has been found in our code. namely, a useful error is bubbled up telling the user that a problem was encountered. very easy to do! (i keep saying that, but it's true) [slide 28] and we're at the end, hopefully i've shown you how to use these simple components together in a robust web application framework. these pieces fit together nicely, and leave you able to focus on the bits that matter, namely how do you get your app's logic working. no complicated SQL, no need to manage HTTP requests, and CherryPy can even manage sessions for you. and finally, very simple but robust form validation, preserving your data's integrity. what's amazing to me is that Bloggy was only 80 lines of Python and 40 lines of HTML templates, hopefully ilustrating how easy it is to get a functional application up and running. enjoy, and hopefully Bloggy and the methods shown here are useful to you for your own application development. thanks!