
Getting Started
+++++++++++++++

Installing Pylons
=================

Read the `Installing Pylons HOWTO <install.html>`_.

Creating a Pylons Project
=========================

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::

    paster create --template=pylons helloworld
    
Windows users might have to use a slightly longer version using the appropriate path to their ``Scripts`` directory::

    python "C:\Python24\Scripts\paster" create --template=pylons helloworld
    
    
This creates a template pylons project which you can use as a basis for your own project. The directory structure is as follows::

    -helloworld

        - helloworld
        - helloworld.egg-info
        - 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. ``setup.cfg`` and the ``helloworld.egg-info`` directory contain extra information to configure how the egg is produced. Distributing and deploying your egg file is covered in the Deployment docs.

The ``helloworld`` directory within the ``helloworld`` directory is where all your application specific code and files are placed. This directory looks like:

    -helloworld
        - helloworld
            - components
            - config
            - controllers
            - docs
            - i18n
            - lib
            - public
            - tests
            - templates
            - __init__.py
            - model.py
            - websetup.py

The ``components`` directory is for Myghty components that you want available in your Myghty templates.

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 most of your code will be written.

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``. # XXX currently a problem in lib.base.py when this command is run but project documentation is generated fine.

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 ``public`` directory is where you put all your HTML, image, javascript, css and other static files. It is similar to your htdocs directory in Apache.

The ``tests`` directroy is where you can put controller and other tests. The controller testing functionality uses TestGears. 

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.

The ``__init__.py`` file is present so that the ``helloworld`` directory can be used as a Python module within the egg.

The ``model.py`` file is for SQLObject classes should you choose to use SQLObject as your database object mapper. SQLObject classes defined in model.py will be loaded and present as model.YourClass inside your controllers. The database configuration string can be set in your ``development.ini`` file.

The ``websetup.py`` should contain any code that should be executed when an end user of your application runs the ``paster setup-app`` command.

You may also notice the Myghty ``cache`` directory which is created the first time you run the code.

Testing the template project
============================

We can test the template project like this::
    
    cd helloworld
    paster serve --reload development.ini
    
Again Windows users may need a slightly longer version of the command last command with the path to their ``Scripts`` directory::

    python "C:\Python24\Scripts\paster" serve  --reload development.ini
    
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://localhost:5000/ you will see the welcome page. 

The command ``paster serve development.ini`` loads our project server configuration file in ``development.ini`` and responds appropriately.

Try creating a new file named ``test.html`` in the ``helloworld/public`` directory with the following content::

    <html>
    <body>
    Hello World!
    </body>
    </html>
    
If you visit http://localhost: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 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``.

Warning: If pylons doesn't appear to be serving the correct content check that it is not because there is a file in the ``public`` directory which is being served first.

Enabling Debugging
==================

If you are developing an application you will want to enable the interactive debugging but it is disabled by default so that you don't accidentally use it on a production site. If you accidentally left debugging on, if an error occured the visitor would be able to execute malicious code.

Enable debugging by commenting out the line that looks like this in the ``[app:main]`` section of your ``development.ini`` file::

    set debug = false
    
so that it looks like this::

    # set debug = false

Now if an error occurs you will be able to interactively debug it.

Creating a Controller and modifying the Routes
==============================================

You're now ready to start creating your own web application. First, lets create a basic hello World controller::

    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://localhost:5000/hello. Put the following text in the file ``helloworld/controllers/hello.py``::

    from helloworld.lib.base import *
    
    class HelloController(BaseController):
        def index(self):
            m.write('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://localhost:5000/hello and the URL http://localhost:5000/ which is the site route. We modify the ``ROUTES CONFIG`` in ``helloworld/config/routing.py`` like this::

    # ROUTES CONFIG
    map = Mapper(directory=root_path+'/controllers')
    
    map.connect(':controller/:action/:id')
    map.connect('', controller='hello', action='index')

This means that route mapper looks for URLs in the form ``controller/action/id`` but that if ``id``, ``action`` or ``controller`` are not specified the defaults in the last line are used.

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: Controller and template changes do *not* require restarting the server even without the ``--reload`` option.)

Visit both http://localhost:5000/hello and http://localhost: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 <http://routes.groovie.org/manual.html>`_.

Using a template
================

Here's an example template, using Myghty, that prints some request information. 

Create a template file ``helloworld/templates/serverinfo.myt`` containing the following::

    <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 you will need to add a new method to your HelloController in ``helloworld/controllers/hello.py``. Add the following function to the end of the class::

    def serverinfo(self):
        m.subexec('/serverinfo.myt')

The m.subexec('/serverinfo.myt') function will call Myghty to render your template. 

If your server is still running you can view the page at: http://localhost:5000/hello/serverinfo

If not simply restart the server with ``paster serve --reload development.ini`` from the helloworld directory. 

Controller variables and Template Globals
=========================================


Pylons Globals
--------------

For convenience, there are several globals (imported from lib.base) available for use in your controllers:

session
    Acts as a dict to store session data, see the `Myghty Session docs <http://www.myghty.org/docs/session.myt#session>`_ for usage details

request
    The current HTTP request object, corresponds to the `r object from Myghty <http://www.myghty.org/docs/globals.myt#globals_globalr>`_. This object contains common methods to
    access request information like request.method, request.headers_in and request.headers_out.

m
    m is the Myghty object, described in `detail in the Myghty docs <http://www.myghty.org/docs/request.myt#request>`_.
    Used primarily for template rendering, and caching functionality.

h
    h is the point at which all the Pylons helper functions are utilized from. By default Pylons will load all the helper functions available from the `Web Helpers </WebHelpers/module-index.html>`_ package. Keep in mind when
    reading the WebHelpers docs that all the functions listed should be prefixed by `h.` under Pylons as
    we use namespaces to keep them organized.

c
    (described in `Passing Variables to Templates`)
    
g
    (described in `Application Global Variables`)

Passing Variables to Templates
------------------------------

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::

    def serverinfo(self):
        c.value = 2 
        m.subexec('/serverinfo.myt')

and modify the ``serverinfo.myt`` file in the ``templates`` directory to look like this::

    <p>The value of <tt>c.value</tt> is: 
    <% c.value %>
    
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::

    <p>Hi there <% c.name or c.full_name or "Joe Smith" %>

There is one rule though, attributes of ``c`` must not start with an ``_`` character so ``c.value = 1`` is fine but ``c._value = 1`` is not. This is because ``c`` has some slightly complicated code which you could accidentally damage if you assigned a variable starting with ``_``. With this rule in place ``c`` is very robust.

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.

Application Globals and Persistent Objects
------------------------------------------

There are occasions where you might want information to be available to all controllers and not to be reset on each request. For example you might want a database connection that is made when the application is loaded, is available on all requests and is closed when the application exits or the server is stopped. 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 class attributes you set in the ``__init__()`` method will be available as attributes of ``g`` throughout your Pylons application. Any attributes you set on ``g`` during one request will remain changed for all the other requests. You have to be very careful of 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::

    def __init__(self, defaults, app, **extra):
        self.message = 'Hello'
        
Then add this new method to the end of the ``helloworld/controllers/hello.py``: 

    def app_globals_test(self):
        if g.message == 'Hello':
            m.write(g.message)
            g.message = 'Hello World!'
        else:
            m.write(g.message)

This time if you run the server and visit http://localhost: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 ``m``, ``r``, ``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.
