Creating an app
===============

The Django web site has a very good
`tutorial <https://docs.djangoproject.com/en/dev/intro/tutorial01/>`_ to
get you familiar with the Django framework. The more you know about
Django, the easier you will find it working with the OmeroWeb framework.
One major feature of Django that we do not use in OmeroWeb is the Django
database mapping, since all data comes from the OMERO server and is
saved back there. You will notice that the models.py files in each app
are empty.

Getting set up
--------------

You will need to have an OMERO server running that you can connect to.
This will typically be on your own machine, although it does not
necessarily have to be. If you want to connect to another server (not
localhost) you can edit the server list as described on the OMERO.web 
deployment page (see :doc:`Unix </sysadmins/unix/install-web>` or 
:doc:`Windows </sysadmins/windows/install-web>` version) and choose that 
server when you log in. That page also describes how to set debug to 'True' 
which is important when developing with OMERO.web and you should also be using 
the Django 'development' server.

You can either add your app to the omeroweb under an OMERO.server release build,
or run directly from the OMERO.web source code:

Option 1: Using OMERO.server release build
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~

If all your edits will be under your own app, and you are not editing or building
the OMERO.web source code, then
the simplest option is to directly add your app to the server build
under lib/python/omeroweb. This code is run when you start the Django
server with

::

    $ bin/omero web start
    Starting django development webserver... 
    Validating models...
    0 errors found

    Django version 1.1.1, using settings 'omeroweb.settings'
    Development server is running at http://0.0.0.0:4080/
    Quit the server with CONTROL-C.

.. note:: Port number is 4080

When you edit and save the code, under lib/python/omeroweb/, Django
automatically detects this and you only need to refresh your browser
to see the changes. You can see this in the :snapshot:`OMERO.web intro
movie <movies/omero-4-3/mov/OmeroWebIntro-4.3.mov>`.

Option 2: Working from source code
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~

Alternatively,if you have checked out the OMERO.server source code and
are building from source, you will have 2 copies of the OMERO.web code -
source code is under components/tools/OmeroWeb/omeroweb and the server
build is under dist/lib/python/omeroweb. You should be editing the
source code since any edits to the build code will get wiped out each
time you build! In order to run Django directly from the source code you
need to follow a few steps (commands are shown below):

-  Set $OMERO_HOME, so that OMERO.web knows where to find config, write logs etc.

   .. note:: You should not set $OMERO_HOME on production servers

-  Make sure that the Django libraries that are under the build:
   dist/lib/python/django are on your PYTHONPATH.
-  Remove the built omeroweb folder, otherwise this will get used
   instead of the source omeroweb 

   .. note:: You have to do this again if you build the server

-  From the source omeroweb/ folder, manually run the Django development
   server

   ::

       $ export OMERO_HOME = ~/Desktop/OMERO/dist      # Example server build path

       # Make sure the Django code etc can be imported
       $ export PYTHONPATH=$OMERO_HOME/lib/python/:$PYTHONPATH
       $ cd $OMERO_HOME
       # need to remove the built omeroweb code so it doesn't get imported
       $ rm -rf lib/python/omeroweb/

       $ cd ../components/tools/OmeroWeb/omeroweb
       $ python manage.py runserver
       Validating models...
       0 errors found

       Django version 1.1.1, using settings 'omeroweb.settings'
       Development server is running at http://127.0.0.1:8000/
       Quit the server with CONTROL-C.

   .. note:: Default port number is 8000. To specify port, use 
       E.g: $ python manage.py runserver 0.0.0.0:4080

You should make sure that you can access the webclient and webadmin on
your local machine before starting to develop your own code. Be sure to
use the correct port number as mentioned above, either:

-  ` http://localhost:4080/webclient/ <http://localhost:4080/webclient/>`_
-  ` http://localhost:8000/webclient/ <http://localhost:8000/webclient/>`_

Creating an app
---------------

We suggest you use github (as we do) since it is much easier for us to
help you with any problems you have if we can see your code. The steps below
describe how to create a stand-alone git repository for your app, similar to 
`webtagging <https://github.com/dpwrussell/webtagging>`_.
If you do not want to use github, simply ignore the github steps below.

The steps below describe setting up a new app. You should choose an
appropriate name for your app and use it in place of <your-app> in the
examples below:

Create and checkout a new github repository OR manually create a new directory
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~

-  Login to your github account homepage (E.g.
   `<https://github.com/>`_\ <your-name>/) and click
   "New repository"
-  Enter the name of <your-app>, add description and choose to add
   README.

-  Change into the /omeroweb/ directory:

   ::

       # running from build
       $ cd lib/python/omeroweb/

       # OR: running from source:
       $ cd components/tools/OmeroWeb/omeroweb

-  Checkout your new repository (into a new directory)

   ::

       $ git clone git@github.com:<your-name>/<your-app>.git


-  OR: If you haven't used git to create your app directory above, then

   ::

        $ mkdir <your-app>

Add the essential files to your app
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~

-  Create an empty file ``<your-app>/__init__.py`` (NB: both double
   underscores)
-  Create urls.py

   ::

       from django.conf.urls.defaults import *
       from omeroweb.<your-app> import views

       urlpatterns = patterns('django.views.generic.simple',

            # index 'home page' of the <your-app> app
            url( r'^$', views.index, name='<your-app>_index' ),

        )

-  Create views.py

   ::

        from django.http import HttpResponse

        def index(request):
            """
            Just a place-holder while we get started
            """
            return HttpResponse("Welcome to your app home-page!")

Add your app to OMERO.web
~~~~~~~~~~~~~~~~~~~~~~~~~

This will add your app to the INSTALLED\_APPS, so that urls are
registered etc.

::

    $ bin/omero config set omero.web.apps '["<your-app>"]'

.. note::

    For releases before 4.4, you need to 'register' your app with Django
    manually by adding it to the INSTALLED\_APPS list in
    omeroweb/settings.py following the pattern of existing apps there. You
    also need to edit omeroweb/urls.py to add your app's urls.py file to the
    list of "urlpatterns". Again, you should be able to follow the existing
    examples there. You can also specify at this point the url under which
    your app will be found.

Now you can view the home-page we created above (NB: you will need to
restart the OMERO.web server for the config settings to take effect)

::

     $ bin/omero web stop
     $ bin/omero web start

Go to ` http://localhost:4080/ <http://localhost:4080/>`_\ <your-app>/
OR ` http://localhost:8000/ <http://localhost:8000/>`_\ <your-app>/
Should see 'Welcome'

Commit your code and push to github
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~

::

    $ git status (see new files, plus .pyc files)
    $ echo "*.pyc" > .gitignore         # ignore .pyc files
    $ echo ".gitignore" >> .gitignore   # ALSO ignore .gitignore

    $ git add ./
    $ git commit -m "Initial commit of bare-bones OMERO.web app"
    $ git push origin master

Connect to OMERO: example
~~~~~~~~~~~~~~~~~~~~~~~~~

We have got our new app working, but it is not connecting to OMERO yet.
Let us create a simple "stack preview" for an Image with multiple
Z-sections. We are going to display the image name and 5 planes evenly
spaced across the Z-stack. You should be able to add the appropriate
code to urls.py, views.py that you created above, and add a template
under /omeroweb/<your-app>/templates/<your-app>/ 

.. note::

   note that /<your-app>/ appears twice in that path (need an extra folder 
   under templates). This example can be found in webtest.

-  **urls.py**

   ::

       url( r'^stack_preview/(?P<imageId>[0-9]+)/$', views.stack_preview, 
            name="<your-app>_stack_preview" ),

-  **views.py** Here we are using the @login\_required decorator to
   retrieve a connection to OMERO from the session key in the http
   request (or provide a login page and redirect here). 'conn' is passed
   to the method arguments. NB: Note a couple of new imports to add at
   the top of your page.

   ::

       from omeroweb.webclient.decorators import login_required
       from django.shortcuts import render_to_response


       @login_required()
       def stack_preview (request, imageId, conn=None, **kwargs):
           """ Shows a subset of Z-planes for an image """
           image = conn.getObject("Image", imageId)       # Get Image from OMERO
           image_name = image.getName()
           sizeZ = image.getSizeZ()                        # get the Z size
           # 5 Z-planes
           z_indexes = [0, int(sizeZ*0.25), 
                    int(sizeZ*0.5), int(sizeZ*0.75), sizeZ-1]
           return render_to_response('webtest/stack_preview.html',
                {'imageId':imageId, 
                'image_name':image_name, 
                'z_indexes':z_indexes})

-  **<your-app>/templates/<your-app>/stack\_preview.html**

   ::

       <html>
       <head>
            <title>Stack Preview</title>
       </head>
       <body>
            <h1>{{ image_name }}</h1>

            {% for z in z_indexes %}
                <img src="{% url webgateway.views.render_image imageId z 0 %}"          
                    style="max-width: 200px; max-height:200px"/>
            {% endfor %}
       </body>
       </html>


Viewing the page at http://localhost:4080/<your-app>/stack_preview/<image-id>/ 
should give you the image name and 5 planes from the Z stack. You will notice 
that we are using webgateway to handle the image rendering using a url 
auto-generated by Django - see :doc:`/developers/Web/WebGateway`.

Resources for writing your own code
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~

The webtest app has a number of examples. If you go to the webtest
homepage E.g. `<http://localhost:8000/webtest>`_ you will
see an introduction to some of them. This page tries to find random
image and dataset from your OMERO server to use in the webtest examples.

Extending templates
~~~~~~~~~~~~~~~~~~~

We provide several html templates in
webgateway/templates/webgateway/base. This is a nice way of giving users
the feeling that they have not left the webclient, if you are providing
additional functionality for webclient users. You may choose not to use
this if you are building a 'stand-alone' web application. In either
case, it is good practice to create your own templates with common
components (links, logout etc), so you can make changes to all your
pages at once. See :doc:`/developers/Web/WritingTemplates` for more info.

OMERO.web plugins (OMERO 4.4)
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~

**This functionality is under development:**

An alternative is to bring your content into the existing webclient. See
omeroweb/settings.py "omero.web.ui.right\_plugins" and
"omero.web.ui.center\_plugins".