=================================
Django Install Package
=================================

:Author: limodou (limodou@gmail.com)
:Blog: http://www.donews.net/limodou
:Date: 2006-02-09

What's it?
===========

It's a small package used for django. I like django very much. And I also want
to make many things automatic. And I also want to using NewEdit_ to help
development of django. So I need some tools which can easy modify the settings.py and
urls.py. Thus I developped some modules for this aim. You can use it to write a 
install script, and it'll automatically install everything for you, e.g., start a 
new project, create a new app, install a existed app. It works like a shell script,
it can execute many similar commands, just like: edit, cd, mkdir, copy, copytree, do, 
mkfile, etc.

.. _NewEdit: http://wiki.woodpecker.org.cn/moin/NewEdit

What's the features?
====================== 

* Can modify settings.py and change, add, delete(comment it) option variable.
* Can modify urls.py and add pattern. The urls.py will get from settings.py.
* Can execute a command list, just like a script
* Support some internal commands and some similar shell commands
* You can extend it easily

Where can I find it and download it?
======================================

* `download version 0.1`_
* svn checkout http://cvs.woodpecker.org.cn/svn/woodpecker/zqlib/tangle/limodou/djangoinstall/trunk

.. _`download version 0.1`: http://wiki.woodpecker.org.cn/moin/LimodouShare?action=AttachFile&do=get&target=djangoinstall.tar.gz

How to feedback?
====================

You can discuss in django maillist or send email to me limodou@gmail.com. But I'll
say sorry for my English. I hope we can understand each other.

This module may not very mature, but I wish it can make the life easy. If you have
any question about it, I hope you can discuss with me and patch is also welcome.

Tutorial
==========

This package include a test script named test_install.py, it'll be a good reference.

.. sidebar:: Table Content

    .. contents:: 

Example 1: Start a new project
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~

You can use djangoinstall package to start a new project. This function may be
very similar with django-admin.py startproject, but it can also automatically
set some variables in settings.py.

Before we start our work, let's confirm some things:

* say the work directory is ``d:/test``
* the target project name will be ``project``
* settings file will be ``settings.py``

#.  Download ``djangoinstall.tar.gz`` and extract to a directory

#.  install the package, just like::

        python setup.py install
    
    .. note:: You should install setuptools module, if not, the ``setup.py`` will automatically
       install it from the internet.
    
#.  Change current directory to ``d:/test``

#.  Create a new file named ``config.ini``

#.  Write donw the code like this::

        root_path = D:\test
        django_project_name = project
        django_project_settings = settings.py
    
    These value will be used for replacement. And it saved the basic info about
    your project. 

    ``root_path``:
        Represent the start working path. Thd django project will be created in it.
        
    ``django_project_name``:
        Project's name, can be used to replace placehold string.
        
    ``django_project_settings``:
        settings.py filename.

#.  Create a new python file (e.g. ``install.py``)

#.  Write down the code like this::

        from djangoinstall import install
        
        #create django_project
        scripts = [
            'cd %(root_path)s',
            'do startproject project',
            'cd project',
            'edit settings DATABASE_ENGINE sqlite3',
            'edit settings DATABASE_NAME %(project_path)s/data.db',
            ('edit settings ADMINS', ("limodou", "limodou@gmail.com")),
            'do init',
        ]
        
        install.main(scripts)
    
    There is many things need to explain. 

    First line is used to import ``install`` module from ``djangoinstall`` package.

    List variable ``scripts`` will hold the commands list.

    Every command just like::

        commandname paramters
    
    The command could be a string, or a tuple. If the command is a string, all 
    parameters need to be separated with blank, just like in shell. And if the 
    command is a tuple(just for modifying settings.py list option variable for now), 
    it will combine with the former part(string).
    
    Different command may include different parameters.

    ``'cd %(root_path)s'``
        just works like in shell. It need one parameter. You can see, the 
        parameter is : ``%(root_path)s``, it means the ``%(root_path)s`` will be 
        replace by the real value named ``root_path``.
    
        .. note:: djangoinstall package will automatically create some internal variables
            for parameters replace. These variables include: ``project_name``, ``project_path``,
            ``root_path``, and so on.
    
    In this case ``root_path`` will be ``d:/test``. But how does it get from. You either 
    pass it from the command line, or write a configure file to hold these value. 
    Will see later as we run the script.
    
    ``'do startproject project'``
        ``do`` command will be converted to::
    
            django-admin.py startproject project
        
        And only when the parameter after ``do`` equal ``startproject``, djangoinstall will 
        use ``django-admin.py``, others will use ``manage.py`` instead. This command 
        can receive any amount parameters just like a shell command.
    
    ``'edit settings DATABASE_ENGINE sqlite3'``
        Modify the settings.py file. ``edit`` command only can be followed by ``settings`` 
        or ``urlconf`` option. Next settings is option name in ``settings.py`` and its value.
        If you look at ``settings.py`` very carefully, you can find there are only two  
        types in ``settings.py``, they are: single value and list(tuple) value. So I write a
        module ``DjangoIni.py`` to parse it. So in here, ``DATABASE_ENGINE`` is a single value,
        and this command is used to set ``DATABASE_ENGINE`` is ``sqlite3``.

    ``('edit settings ADMINS', ("limodou", "limodou@gmail.com"))``
        This command is not a string but a tuple, and the second element is also a tuple.
        This is the second format of the command. Because ADMINS option need a tuple value.
    
    ``'do init'``
        It will be converted to::
    
            manage.py init
        
    So till now, the prepare work is ready, lets run the script to see what would happen.

#.  Run the script::

        python install.py
    
    Because you have create a file ``config.ini``, so above instruction is the easiest way. 
    You can also execute ``python install.py -h`` to see the help message. And you also can
    specify a config file using ``-c`` option. Some variables also can be supplied through
    options.
    
Then you may see the project is created and settings.py is changed correctly. Even the 
database is also created. But if you run the script twice, you will find exception rose. 
Because the djangoinstall package only a helper module which used to script the 
configuration automatically, and it also will call the django commandline, so I couldn't
promise that I could catch all error output. And there also lacks transaction protection.
But if you test carefully, I think the script will works very well in other boxes.

Example 2: Install Admin App
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~

Don't want to say so much again, just the script code of ``install.py``::

    scripts = [
        'edit settings INSTALLED_APPS django.contrib.admin',
        ('edit urlconf', r'^admin/', "include('django.contrib.admin.urls')"),
        'do install admin',
    ]

Here is something to note: if the setting option variable is a list, the value will
be append to the list, if there is no entry already existed.

``('edit urlconf', r'^admin/', "include('django.contrib.admin.urls')")``
    Here the command is a tuple, you should be careful. And you are modifying urlconf 
    file(``urls.py``), but not ``settings.py.``
    
    
Example 3: A More Complex Script
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~

::

    scripts = [
        ('mkdir media'),
        ('copytree %(from_path)s/media media'),
        ('copytree %(from_path)s/package address'),
        ('mkdir templates/address'),
        ('copytree %(from_path)s/templates templates/address'),
        ('edit settings INSTALLED_APPS %(project_name)s.address'),
        ('edit urlconf', r'^address/', 'include("newtest.address.urls")'),
        ('do install admin'),
    ]

Here you can see some others command, just like: mkdir, copytree. They are very simple. 
And a new internal variable ``from_path``. ``from_path`` is represent the directory where 
you run the script. This example demenstrates files and directories manipulation.

Command Summary
==================

*   ``do parameter``

    will be convert ``django-admin.py parameters`` (only for startproject) or 
    ``manage.py parameters`` .Used to execute django commandline.
    
    e.g::
    
        'do init'
        'do install admin'
    
*   ``cd directory``

    change current directory to special directory.
    
    e.g::
    
        'cd d:/test'
    
*   ``edit settings|urlconf option_name value``

    modify settings.py or urls.py file
    
    e.g::
        
        'edit settings INSTALLED_APPS django.contrib.admin'
        ('edit settings ADMINS', ("limodou", "limodou@gmail.com"))
        ('edit urlconf', r'^address/', 'include("newtest.address.urls")')
    
*   ``mkdir directory``

    make directory. 
    
    e.g:: 
    
        'mkdir d:/test/project/media'
    
*   ``mkfile filename``

    create an empty file, just like ``__init__.py``. 
    
    e.g::
    
        mkfile %(project_path)s/test/templatetags/__init__.py
        
*   ``copy sourcefile destfile/destdir``

    copy sourcefile to destfile or destdir. And sourcefile also can include 
    asterisk wildcard, it works with ``glob`` module. 
    
    e.g::
    
        'copy %(from_path)s/media/*.css media'
        
    One thing you should know that, if the destfile/destdir is a relative path,
    its base directory will be project directory first, unless you changed 
    current directory in commands.
    
*   ``copytree sourcedir destdir``

    copy all the files and subdirectories in sourcedir to destdir.
    
    e.g::
    
        'copytree %(from_path)s/templates/address templates/address'
        
Internal Variables Summary
=============================

Internal variables can be used to replace placehold in command. The exampls above
show many cases about it, just like ``%(from_path)s``. Here is a list of these variables.

*   from_path

    the directory where the script be executed
    
*   root_path

    set in configuration file or pass from command parameter, represent the project
    root path. The djano project directory will be it's subdirectory.
    
*   project_name

    Django project name
    
*   project_path

    equal: ``os.path.join(root_path, project_name)``


Advanced Topic
=================

(empty)
