Hi fellas, hope you’re already flying high with GAE and have your own Amazon product store set up after reading my previous post series on how to Set up an Amazon Book Store on Google App Engine! GAE supports a number of Python web frameworks. See what the Google App Engine site says:

” Google App Engine supports any framework written in pure Python that speaks CGI (and any WSGI-compliant framework using a CGI adaptor) ”

One such framework is ‘Bottle’. Its lightweight (literally, 72 KB only and one file has it all !). This is what ‘Bottle’ s website says:

Bottle is a fast, simple and lightweight WSGI micro web-framework for Python. It is distributed as a single file module and has no dependencies other than the Python Standard Library.

  • Routing: Requests to function-call mapping with support for clean and dynamic URLs.
  • Templates: Fast and pythonic built-in template engine and support for mako, jinja2 and cheetah templates.
  • Utilities: Convenient access to form data, file uploads, cookies, headers and other HTTP related metadata.
  • Server: Built-in HTTP development server and support for paste, fapws3, bjoern, Google App Engine, cherrypy or any other WSGI capable HTTP server.

Bottle might not be a full fledged framework like Django, Pylons etc. but I may say it is ideal for small to medium applications.

In this small article I’ll explain how to use Bottle with Google App Engine.

Lets start with the prerequisites:

  • Google App Engine and Python 2.5: Download and install Python 2.5 from here. and the GAE sdk for Python from here. It’ll be an advantage if you complete atleast the ‘Hello World’ tutorial from the docs.
  • Bottle: Get a copy of Bottle from here. You can also use ‘easy_install’ to install it in your Python installation. All we need is the ‘bottle.py’ file. Get the documentation from here: Bottle docs. It has a very good tutorial for getting started with Bottle. Though it’s not mandatory that you complete the tutorial, I’ll explain as much as possible.

Make a new folder in a location of your choice, name it ‘bottleapp’ (you can name it whatever you want, as far as you remember the path and the folder name while running the app). Put the following folders in the ‘bottleapp’ folder:
>bottleapp
>>>framework
>>>templates
>>>styles

Extract the downloaded Bottle tar archive, copy the file ‘bottle.py’ to ‘framework’. If you chose ‘easy_install’ then ‘bottle.py’ can be found in the following location:
C:\Python25\Lib\site-packages\bottle-0.8.5-py2.5.egg\
(I’m on Windows, your path depends on your OS, but it’s the same from ‘Python25’ onwards. Bottle version might differ.) Create an empty Python file and save it as ‘__init__.py’ in the ‘framework’ folder. This file allows us to import the framework as a module from the ‘framework’ folder.

Now create a config file, that is ‘app.yaml’ and save it in the root folder, i.e. bottleapp. Put the following in it:
[html]
application: my-bottle-app
version: 1
runtime: python
api_version: 1

handlers:
– url: /styles
static_dir: styles

– url: /.*
script: main.py
[/html]

We’re naming our app as ‘my-bottle-app’. It’s version 1 of our app, uses the python runtime and GAE api_version is 1. ‘handlers’ specifies that whenever ‘styles’ is appended to the url, load the ‘styles’ folder that holds the stylesheets for our app. All the urls will be handled by ‘main.py’.

Now make a new Python file and put the following code into it:
[python]
from framework import bottle
from framework.bottle import route, template, request, error, debug
from google.appengine.ext.webapp.util import run_wsgi_app

@route(‘/’)
def DisplayForm():
message = ‘Hello World’
output = template(‘templates/home’, data = message)
return output

def main():
debug(True)
run_wsgi_app(bottle.default_app())

@error(403)
def Error403(code):
return ‘Get your codes right dude, you caused some error!’

@error(404)
def Error404(code):
return ‘Stop cowboy, what are you trying to find?’

if __name__=="__main__":
main()
[/python]

Save it as ‘main.py’ in the root folder i. e. bottleapp folder.
This is a very simple ‘Hello World’ example to check if everything is in place and running. Here’s what the code does:
Import the ‘Bottle’ framework from the ‘framework’ folder. Import the decorators ‘route’ and ‘error’. ‘route’ maps the urls to handlers and ‘error’ is used to handle errors like 404, 403 etc. (More on decorators, route and error). Import the modules ‘template’ – the Simple Template Engine packed along with Bottle, ‘request’ – used to handle the types of requests GET, POST, DELETE etc., ‘debug’ – used to trace and print errors so that you know where to look and correct. ‘debug’ is used only while developing the application, not on a production server.

We use the ‘route’ decorator to map the root (‘/’) url to the handler ‘DisplayForm’. So when the root url is accessed, the ‘DisplayForm’ function is called. ‘DisplayForm’ displays a simple message on the page using the ‘template’ function to render the template ‘home’ which is stored in the ‘templates’ folder. 2 ‘error’ decorators are mapped to 2 functions, one for 404 error and the other for 403. The main function runs the app.

Let’s make the ‘home’ template now. Make a new file and put the following code in it:
[html]
<html>
<body>
<h2>{{ data }}</h2>
</body>
</html>
[/html]

Save this file as ‘home.tpl’ in the templates folder. ‘data’ corresponds to ‘data = message’ that we passed in template(‘templates/home’, data=message). You can pass any Python object type, string, list, dictionary, tuple etc. If you name your template as ‘page.tpl’ then you pass it without the extension as template(‘page’).

Its time to see the app in action. Run the app using ‘dev_appserver.py ‘. Visit the url http://localhost:8080/ in your browser. If you didn’t mess anything, then you should see the homepage with ‘Hello World’ written. Congrats! You have successfully used Bottle framework with GAE.

Next, we see how to use requests for form processing with Bottle.
Modify the main.py file, and add the following code to the DisplayForm function:

[python]
output = template(‘templates/home’)
return output
[/python]

Notice we don’t pass a data variable to the template function, because we just want to display a page with a form when the root url is visited. Now modify the ‘home’ template and replace everything with the following:
[html]
<html>
<head>
<link type=’text/css’ rel=’stylesheet’ href=’/styles/styles.css’ />
</head>
<body>
<div id=’wrap’>
<form action=’/save’ method=’POST’>
Name:<br /> <input type=’text’ name=’name’ /> <br />
Gender:<br /> <select name=’gender’>
<option value=’male’>Male</option>
<option value=’female’>Female</option>
</select>
<br />
Age:<br /> <input type=’text’ name=’age’ > <br />
Address:<br /> <textarea name=’add’></textarea> <br />

<input type=’submit’ value=’Save’ />
</form>
</div>
</body>
</html>
[/html]

Save the file, and try visiting the root url now. You should see a form displayed. We’ve set the form method to ‘POST’. The action is set to ‘/save’. That means ‘save’ will be appended to the root url when the form is submitted with some data. Don’t submit it yet, we need to handle this new url with a ‘route’ mapping.

Add a new function to ‘main.py’ :
[python]
@route(‘/save’, method=’POST’)
def ProcessForm():
name = request.POST.get(‘name’, ”).strip()
gender = request.POST.get(‘gender’, ”).strip()
age = request.POST.get(‘age’, ”).strip()
address = request.POST.get(‘add’, ”).strip()

values = {‘name’:name, ‘gender’:gender, ‘age’:age, ‘address’:address}

return template(‘templates/data’, data = values)
[/python]

We’re mapping ‘/save’ to the ‘ProcessForm’ handler. The method is set to ‘POST’. You can change it to ‘GET’ if you’ve set the form method to GET. Inside this handler, we’re getting the values of the form fields. name = request.POST.get(‘name’, ”).strip(), gets the value of the text field which has the name ‘name’, similarly for the select ‘gender’, fields ‘age’ and ‘address’.
We combine these values in a Python dictionary object ‘values’ and pass it to the template function for rendering on the template. This time we use a new template, ‘data’.

Here’s the ‘data’ template:
[html]
<html>
<head>
<link type=’text/css’ rel=’stylesheet’ href=’/styles/styles.css’ />
</head>
<body>
<div id=’wrap’>
<p>Hello {{ data[‘name’] }}</p>
<p> Your Data: </p>
%if data[‘gender’]==’male’:
<p>Mr. {{data[‘name’]}}</p>
%elif data[‘gender’] == ‘female’:
<p>Ms./Mrs. {{data[‘name’]}}</p>
%end
<p>{{ data[‘age’] }}</p>
<p>{{ data[‘address’] }}</p>
</div>
</body>
</html>
[/html]

Save this as ‘data.tpl’ in the ‘templates’ folder. There’s a lot’s of template specific code in this. {{ data[‘name’] }} outputs the variable name directly. Python code is written with a preceding ‘%’ sign. Every block should have a corresponding ‘%end’ tag. No need to worry about indentation, it’s taken care of internally by Bottle.

Run the application again, and visit the root url http://localhost:8080/, fill in the details, and click ‘Save’. You should see the data page with the data values you entered in the form.

Here’s the last thing we need, a stylesheet to make our application look good ! Make a new file and add the following styles to it:
[css]
body{ background-color: beige; }
#wrap{ border:1px solid green; height: 230px; width:300px; padding: 20px;}
[/css]

Save this as ‘styles.css’ in the ‘styles’ folder. Reload the browser and now you have a styled application !
Congrats again for your new Google App Engine application using ‘Bottle’ Python framework! Jump to the Bottle documentation for learning the framework more neatly. Any doubts, queries or improvements, contact me: mail@rutwick.com, @tweetrut.

By rutwick

36 thoughts on “Use Bottle Python framework with Google App Engine”
    1. YES… You can!

      Bottle’s not made ‘only’ for GAE (like Tipfy), it works alone as well (like Django) ! The single code file comes with a development server of its own and a templating engine. You can opt not to use the dev server when your non GAE app is put on the production server, a Python powered server. Read ‘Server’ over here: http://bottle.paws.de/docs/dev/index.html
      Haven’t used Sinatra yet, so can’t comment on it !

    1. You are welcome Adam!
      Feel free to contact me if you need more help on GAE.
      And do checkout my other App Engine posts!
      -Rutwick

  1. A most helpful walkthrough, thank you.
    I did notice that when I stuffed up the name of the data template, I got the error:
    ImportError: Could not generate the error page. Please add bottle to sys.path

    Bottle was setup as standard in the D:\Python27\Lib\site-packages folder

    1. Your welcome… glad you found it useful!
      You get the ‘ImportError’ if Bottle is not found, that’s why I mentioned packing Bottle.py along with your app. Just make a folder in your main app folder, put Bottle.py and create an empty ‘__init__.py’ file in this folder. Then import it in your app, you won’t get that error!
      Try if this works, and let me know!

      1. Does not appear to work for me. I had created the framework folder and added bottle.py and __init__.py following your instructions. When I corrected the file name for the data template your demo worked fine because there was no longer an error response. However extending the example towards my ultimate needs soon got me into the same state (with 500 errors).

        The Bottle documentation for GAE simply says…
        “The gae adapter completely automates the Google App Engine deployment. It even ensures that a main() function is present in your __main__ module to enable App Caching (which drastically improves performance):
        import bottle
        # … build or import your bottle application here …
        bottle.run(server=’gae’)”
        which is hard to understand unless you have already been there and done that!

  2. you forgot to make your app.cfg – will not launch locally (afaik) without it…
    gmilby@mini64:~/google_appengine$ python appcfg.py update bottleapp/

  3. THANK YOU EVER SO MUCH.cant believe the hustle i have gone through to make bottle work on GAE, dumped web2py framework simply because getting it to run on GAE isn’t easy when you are working from a windows platform.bottle runs beautifully and is well simply awesome!thanks again for the article its simply perfect for noobs like me 😀

    1. Hi Kesh,

      You’re welcome my friend !
      Glad it helped you ! I found web2py a little too confusing! Bottle is so small and easy to get running on GAE, you can pack it along with your app. Even Tipfy is bigger than bottle !

      -Rutwick

  4. Thanks, helped me.

    Has anyone succeeded in running Bottle 0.9.3 with app engine and the Windows SDK? I could only get 0.8.5 to run.

    1. Hey Orip, sorry for the late reply!
      I think I should try running Bottle 0.9.3 with GAE, because another person asked me the same question.

      And I’m Glad the article helped you!

      -Rutwick

    1. Hi Vaibhav, extremely sorry for replying late, been a little busy with work!
      I haven’t tried GAE with Bottle 0.9.3, but I will definitely see how it goes. Will let you know if it works or not!

      -Rutwick

  5. I just spun up a Bottle.py app on GAE according to their docs. It’s working except that when I change my templates the changes don’t take effect unless I restart GAE. Setting bottle.debug(True) is supposed to prevent template caching, but it doesn’t. I even tried bottle.TEMPLATES.clear(). Does this work for anyone else?

  6. Hi this is real nice, but can you extend this with an example of include/rebase?

    I couldnt get the include and rebase work in appengine 🙁

    thanks

  7. I just wanted to say thanks. We’re looking into bottle ATM and your tutorial is a perfect way to get started and try it out.

    1. Thanks man! Yeah I’m actually thinking of it.. but not getting the time! Can you do it and put it on your blog? I’ll give a link to your post…
      Let me know bro…

Leave a Reply

Your email address will not be published. Required fields are marked *