Bottle logo

Developing with Bottle

by Real Python basics web-dev

I love bottle. It’s a simple, yet fast and powerful Python micro-framework, perfect for small web applications and rapid prototyping. It’s also an excellent learning tool for those just getting starting with web development.

Let’s look at a quick example.

NOTE: This tutorial assumes you are running a Unix-based environment - e.g, Mac OS X, a Linux flavor, or a Linux flavor powered through a virtual machine.

Updated 06/13/2015: updated code examples and explanations

Starting Up

First, let’s create a directory to work in:

Shell
$ mkdir bottle && cd bottle

Next, you need to have pip, virtualenv, and git installed.

virtualenv is a Python tool that makes it easy to manage the Python packages needed for a particular project; it keeps packages in one project from conflicting with packages in other projects. pip, meanwhile, is a package manager used for managing the installation of Python packages.

For help with installing pip (and it’s dependencies) in a Unix environment, follow the instructions in this Gist. If you are on Windows environment, please view this video for help.

Once you have pip installed, run the following command to install virtualenv:

Shell
$ pip install virtualenv==12.0.7

Now we can easily setup our local environment:

Shell
$ virtualenv venv
$ source venv/bin/activate

Install bottle:

Shell
$ pip install bottle==0.12.8
$ pip freeze > requirements.txt

Finally, let’s put our app under version control using Git. For more information on Git, please view this article, which also includes installation instructions.

Shell
$ git init
$ git add .
$ git commit -m "initial commit"

Writing Your App

We’re ready to write our bottle app. Open Sublime Text 3 or your text editor of choice. Create your application file, app.py, which will hold the entirety of our first app:

Python
import os
from bottle import route, run, template

index_html = '''My first web app! By <strong>{{ author }}</strong>.'''


@route('/')
def index():
    return template(index_html, author='Real Python')


@route('/name/<name>')
def name(name):
    return template(index_html, author=name)


if __name__ == '__main__':
    port = int(os.environ.get('PORT', 8080))
    run(host='0.0.0.0', port=port, debug=True)

Save the file.

Now you can run your app locally:

Shell
$ python app.py

You should be able to connect to http://localhost:8080/ and see your application running!

My first web app! By RealPython.

So, the @route decorator binds a function to the route. In the first route, /, the index() function is bound to the route, which renders the index_html template and passes in a variable, author, as a keyword argument. This variable is then accessible in the template.

Now navigate to the next route, making sure to add your name on the end of the route - i.e., http://localhost:8080/name/Michael. You should see something like:

My first web app! By Michael.

What’s going on?

  1. Again, the @route decorator binds a function to the route. In this case, we’re using a dynamic route that includes a wildcard of <name>.
  2. This wildcard is then passed to the view function as an argument - def name(name).
  3. We then passed this to the template as a keyword argument - author=name
  4. The template then renders the author variable - {{ author }}.

Shell Script

Want to get started quickly? Generate the starter app in a few seconds using this Shell script.

Shell
mkdir bottle
cd bottle
pip install virtualenv==12.0.7
virtualenv venv
source venv/bin/activate
pip install bottle==0.12.8
pip freeze > requirements.txt
git init
git add .
git commit -m "initial commit"

cat >app.py <<EOF
import os
from bottle import route, run, template

index_html = '''My first web app! By <strong>{{ author }}</strong>.'''


@route('/')
def index():
    return template(index_html, author='Real Python')


@route('/name/<name>')
def name(name):
    return template(index_html, author=name)


if __name__ == '__main__':
    port = int(os.environ.get('PORT', 8080))
    run(host='0.0.0.0', port=port, debug=True)
EOF

chmod a+x app.py

git init
git add .
git commit -m "Updated"

Download this script from this Gist, and then run it using the following command:

Shell
$ bash bottle.sh

Next Steps

From this point, it is as easy as adding new @route-decorated functions to create new pages.

Creating the HTML is simple: In the above app, we just inlined the HTML in the file itself. It’s easy to modify this to load the template from a file. For example:

Python
@route('/main')
def main(name):
    return template('main_template')

This will load the template file main_template.tpl, which must be placed in a views folder within your project structure, and render it to the end user.

Refer to the bottle documentation for more info.


We’ll look at how to add additional pages and templates in subsequent posts. However, I urge you to try this on your own. Post any questions as comments below.

Check out Part 2!

🐍 Python Tricks 💌

Get a short & sweet Python Trick delivered to your inbox every couple of days. No spam ever. Unsubscribe any time. Curated by the Real Python team.

Python Tricks Dictionary Merge

Master Real-World Python Skills With Unlimited Access to Real Python

Locked learning resources

Join us and get access to thousands of tutorials, hands-on video courses, and a community of expert Pythonistas:

Level Up Your Python Skills »

Master Real-World Python Skills
With Unlimited Access to Real Python

Locked learning resources

Join us and get access to thousands of tutorials, hands-on video courses, and a community of expert Pythonistas:

Level Up Your Python Skills »

What Do You Think?

Rate this article:

What’s your #1 takeaway or favorite thing you learned? How are you going to put your newfound skills to use? Leave a comment below and let us know.

Commenting Tips: The most useful comments are those written with the goal of learning from or helping out other students. Get tips for asking good questions and get answers to common questions in our support portal.


Looking for a real-time conversation? Visit the Real Python Community Chat or join the next “Office Hours” Live Q&A Session. Happy Pythoning!

Keep Learning