Warning
This documentation does not refer to the most recent version of Pylons. Current Documentation
If you haven't done so already read the installation instructions. This document gives you a quick overview of the basic tasks many people will be interested in doing.
Pylons uses Paste to create and deploy projects as well as create new controllers and their tests.
Create a new project named helloworld with this command:
1 | $ paster create --template=pylons helloworld |
Note: Windows users must configure their PATH as described in Windows Notes, otherwise they must specify the full path name to the paster command.
This creates a new Pylons project which you can use as a basis for your own project. The directory structure is as follows:
1 2 3 4 5 6 7 8 | - helloworld
- data
- helloworld
- helloworld.egg-info
- Various files including paste_deploy_config.ini_tmpl
- development.ini
- setup.cfg
- setup.py
|
The setup.py file is used to create a re-distributable Python package of your project called an egg. Eggs can be thought of as similar to .jar files in Java. The setup.cfg file contains extra information about your project and the helloworld.egg-info directory contains information about the egg including a paste_deploy_config.ini_tmpl file which is used as a template for the config file when users of your project issue a paster make-config command. Distributing and deploying your egg is covered in the Distributing Your Project documentation and end user configuration is described in Application Setup.
You may also notice a data directory which is created the first time you run the code. You can configure the location of the data directory by editing your development.ini file. This directory will hold cached data and sessions used by your app while its running.
The helloworld directory within the helloworld directory is where all your application specific code and files are placed. The directory looks like this:
1 2 3 4 5 6 7 8 9 10 11 12 13 | - helloworld
- helloworld
- config
- controllers
- docs
- i18n
- lib
- models
- public
- templates
- tests
- __init__.py
- websetup.py
|
The config directory contains the configuration options for your web application.
The controllers directory is where your application controllers are written. Controllers are the core of your application where the decision is made on what data to load, and how to view it.
The docs directory is where you can write documentation for your project. You can then turn it into HTML using the command setup.py pudge.
The i18n directory is where your message catalogues are stored to support multiple languages.
The lib directory is where you can put code that is used between different controllers, third party code, or any other code that doesn't fit in well elsewhere.
The models directory is for your model objects, if you're using an ORM this is where the classes for them should go. Objects defined in models/__init__.py will be loaded and present as model.YourObject inside your controllers. The database configuration string can be set in your development.ini file.
The public directory is where you put all your HTML, images, Javascript, CSS and other static files. It is similar to the htdocs directory in Apache.
The tests directory is where you can put controller and other tests. The controller testing functionality uses Nose and paste.fixture.
The templates directory is where templates are stored. Templates contain a mixture of plain text and Python code and are used for creating HTML and other documents in a way that is easy for designers to tweak without them needing to see all the code that goes on behind the scenes. Pylons uses Myghty templates by default but also supports Cheetah, Kid and others through a system called Buffet. See how to change template languages
The __init__.py file is present so that the helloworld directory can be used as a Python module within the egg.
The websetup.py should contain any code that should be executed when an end user of your application runs the paster setup-app command described in Application Setup. If you're looking for where to put that should be run before your application is, this is the place.
We can test the template project like this:
1 2 | $ cd helloworld $ paster serve --reload development.ini |
The command loads our project server configuration file in development.ini and serves the Pylons application.
The --reload option ensures that the server is automatically reloaded if you make any changes to Python files or the development.ini config file. This is very useful during development.
If you visit http://127.0.0.1:5000/ you will see the welcome page (127.0.0.1 is a special IP address that references your own computer but you can change the hostname by editing the development.ini file).
Try creating a new file named test.html in the helloworld/public directory with the following content:
1 2 3 4 5 | <html> <body> Hello World! </body> </html> |
If you visit http://127.0.0.1:5000/test.html you will see the message Hello World!. Any files in the public directory are served in the same way they would be by any webserver, but with built-in caching, and if Pylons has a choice of whether to serve a file from the public directory or from code in a controller it will always choose the file in public. This behavior can be changed by altering the order of the Cascade in config/middleware.py.
The interactive debugger is a powerful tool for use during application development. It is enabled by default in the development environment's development.ini. When enabled, it allows debugging of the application through a web page after an exception is raised. On production environments the debugger poses a major security risk; so production ini files generated from the paster make-config command will have debugging disabled.
To disable debugging, uncomment the following line in the [app:main] section of your development.ini:
1 | #set debug = false
|
to:
1 | set debug = false |
Again; debug must be set to false on production environments as the interactive debugger poses a MAJOR SECURITY RISK.
More information is available in the Interactive Debugger documentation.
You're now ready to start creating your own web application. First, lets create a basic hello World controller:
1 | $ paster controller hello
|
This paster command will create the controllers/hello.py file for you with a basic layout as well as a helloworld/tests/functional/test_hello.py that is used for running functional tests of the controller.
Here's what a basic controller looks like to print out 'Hello World' and respond to http://127.0.0.1:5000/hello. Put the following text in the file helloworld/controllers/hello.py:
1 2 3 4 5 | from helloworld.lib.base import * class HelloController(BaseController): def index(self): return Response('hello world') |
Pylons uses a powerful and flexible system for routing URLs to the appropriate piece of code and back.
We would like the hello controller to also be displayed for both the URL http://127.0.0.1:5000/hello and the URL http://127.0.0.1:5000/ which is the site route. We need to add a line to the routes config in helloworld/config/routing.py so it looks like this:
1 2 3 | map.connect('', controller='hello', action='index') map.connect(':controller/:action/:id') map.connect('*url', controller='template', action='view') |
This means that an empty URL is matched to the index action of the hello controller otherwise the route mapper looks for URLs in the form controller/action/id but if action or controller are not specified the request is routed to the view action of the templates controller where by default a 404 error is raised.
Since we have made changes to our routes we must restart the server. If you are using the --reload option this will happen automatically, otherwise close the old server and start it again using the same command as before. (Note: Myghty template changes do not require restarting the server even without the --reload option.)
Visit both http://127.0.0.1:5000/hello and http://127.0.0.1:5000/ and you will find that although the first URL produces the expected Hello World, the second URL produces the welcome page as before. This is because, as mentioned earlier, static files in the public directory are served before looking for code.
Delete the file public/index.html and the application works as expected.
More information on routes can be found in the Routes manual.
When your controller's action is called it is expected to either call a WSGI application or return a Response object. In the previous section we saw a basic example which returned a new Response object. To render templates, there's the render command, and the render_response command. The latter will render the template, and return it as the content of a new Response object.
Note
For the gory details on the available options to render and render_response, look at the Pylons templating API.
Here's an example template, using Myghty, that prints some request information.
Create a template file helloworld/templates/serverinfo.myt containing the following:
1 2 3 4 5 6 | <p>Hi, here's the server environment: <br /> <% str(request.environ) %></p> <p> and here's the URL you called: <% h.url_for() %> </p> |
To use this template add a new method to your HelloController in helloworld/controllers/hello.py with the following function at the end of the class:
1 2 | def serverinfo(self): return render_response('/serverinfo.myt') |
The render_response('/serverinfo.myt') function will render your template using the default template engine (Myghty).
If your server is still running you can view the page at: http://127.0.0.1:5000/hello/serverinfo
If not simply restart the server with paster serve --reload development.ini from the helloworld directory.
Sessions come enabled for your application and are handled by Beaker middleware, which uses the powerful Myghty container API. This provides robust and powerful sessions as well as caching abilities.
Using a session is very easy, here's what using and saving a session in the above function would look like:
1 2 3 4 | def serverinfo(self): session['name'] = 'George' session.save() return render_response('/serverinfo.myt') |
Session options can be customized via your development.ini file, and use the same names as the Myghty docs for sessions.
Note
Remember to always call session.save() before returning a response to ensure that the session is saved.
For convenience, there are several globals (imported from lib.base) available for use in your controllers:
Pylons controllers are created for each request. This means you can attach variables to self if you want them passed around. However, it can be very inconvenient to keep track of all the variables and methods attached to self, especially if you want to pass them to a template.
To make it easier to set up your data for use by the template, the variable c is made available and is also available in all Myghty templates as the c global. Let's take a look at using it:
1 2 3 | def serverinfo(self): c.value = 2 return render_response('/serverinfo.myt') |
and modify the serverinfo.myt file in the templates directory to look like this:
1 2 | <p>The value of <tt>c.value</tt> is: <% c.value %> |
Note
The c object is available in the other template languages.
You should see 2 printed out on the page. If you ask for an attribute on c that does not exist, rather than throwing an Attribute error, an empty string will be returned. This makes it easy to toggle behavior depending on the response. For example:
1 | <p>Hi there <% c.name or c.full_name or "Joe Smith" %> |
Warning
Be careful when setting c attributes that begin with an _ character. c and other global variables are really a StackedObjectProxies, which reserve the attribute names _current_obj, _push_object and _pop_object for their internal methods.
The c global is also reset on each request so that you don't need to worry about a controller still having old values set from a previous request.
There are occasions where you might want information to be available to all controllers and not reset on each request. For example you might want to initiate a TCP connection that is made when the application is loaded. You can do this through the g variable.
The g variable is an instance of your Globals class in your application's lib/app_globals.py file. Any attributes set in the __init__() method will be available as attributes of g throughout your Pylons application. Any attributes set on g during one request will remain changed for all the other requests. You have to be very careful when setting global variables in requests.
Here is an example of using the g variable. First modify your lib/app_globals.py Globals class so that the __init__.py method looks like this:
1 2 | def __init__(self, global_conf, app_conf, **extra): self.message = 'Hello' |
Then add this new method to the end of the helloworld/controllers/hello.py:
1 2 3 4 5 6 7 8 | def app_globals_test(self): resp = Response() if g.message == 'Hello': resp.write(g.message) g.message = 'Hello World!' else: resp.write(g.message) return resp |
This time if you run the server and visit http://127.0.0.1:5000/hello/app_globals_test/ you should see the message Hello. If you visit the page again the message will be changed to Hello World! and it will remain changed for all subsequent requests because the application global variable was modified on the first request.
The __init__() method takes the parameters global_conf and app_conf which are the values of the global_conf and application configuration variables specified in the development.ini file. This means you can set global variables based on configuration options. Note that you do not have access to c, h or other variables when adding application globals since they are setup before a request is ever made.
You can add code to the __del__() method to be run when the application exits.