Creating a New Django App - ngageoint/voxel-globe GitHub Wiki

Creating a New Django App

In voxel globe, a typical app has two parts. The order page and the processing task that runs the actual algorithm

Adding Order Page

  1. ./just manage startapp {app_name}

  2. Edit voxel_globe/vip/urls.py, add a new url to the urlpatterns tuple

  3. Add the order url entry

     url(r'^apps/{app_name}/', 
         include('voxel_globe.{app_name}.urls', 
         namespace='{app_name}')),
    
  4. Create and edit voxel_globe/{app_name}/urls.py to contain the new django endpoints, typically

     from django.conf.urls import patterns, url
     import voxel_globe.{app_name}.views as views
    
     urlpatterns = patterns('',
         url(r'^$', views.make_order, name='make_order'),
         url(r'^status/(?P<task_id>\d+)$', views.order_status, name="order_status"),
         )
    
  5. Edit voxel_globe/{app_name}/views.py, typically

     from django.shortcuts import render, redirect
     from .forms import {AppName}Form
    
     def make_order(request):
       if request.method == 'POST':
         form = {AppName}Form(request.POST)
    
         if form.is_valid():
           import voxel_globe.{app_name}.tasks as tasks
    
           image_id = form.data['image']
    
           task = tasks.{task_name}.apply_async(args=(image_id,))
    
           return redirect('{app_name}:order_status', task_id=task.id)
       else:
         form = {AppName}Form()
    
       return render(request, 'order/{app_name}/html/make_order.html',
                     {'title': 'Voxel Globe - {App Title here}',
                      'page_title': 'Voxel Globe - {App Page Title here}',
                      'form':form})
    
     def order_status(request, task_id):
       from celery.result import AsyncResult
       
       task = AsyncResult(task_id)
    
       return render(request, 'order/{app_name}/html/order_status.html',
                     {'title': 'Voxel Globe - {App Title here} Status',
                      'page_title': 'Voxel Globe - {App Page Title here} Status',
                      'task': task})
    
  6. Create and edit voxel_globe/{app_name}/forms.py to add the order form, for example

     from django import forms
     import voxel_globe.meta.models as models
    
     class {AppName}Form(forms.Form):
       image = forms.ModelChoiceField(label="Height image", 
           queryset=models.Image.objects.filter(name__startswith='Height Map', 
               newerVersion=None).order_by('name'))
    
  7. Create and edit voxel_globe/{app_name}/templates/{app_name}/html/make_order.html

     {% extends "main/common_header.html" %}
     {% load staticfiles %}
    
     <!-- Include the client side javascript code -->
     {% block includes %}
    
     <style>
     </style>
    
     {% endblock %}
    
     {%block globalfunctions %}
     // Global functions defined outside of the jquery document ready function can be put here.
     {% endblock %}
    
     {% block javascript %}
    
     {% endblock %}
    
     {% block content %}
     <div id="mainContainer" class="main-content">
    
     <form action="{% url '{app_name}:make_order' %}" method="post">
         {% csrf_token %}
         <table>
         {{ form.as_table }}
         </table>
         <input type="submit" value="Submit" />
     </form>
    
    
     </div>
     {% endblock %}
    
  8. Create and edit voxel_globe/{app_name}/templates/{app_name}/html/order_status.html, for example

    {% extends "main/common_header.html" %}
    {% load staticfiles %}
    
    {% block includes %}
    <META http-equiv="refresh" content="5">
    {% endblock %}
    
    {% block content %}
    <div id="mainContainer" class="main-content">
    
    Task ID: {{ task.task_id }}<BR>
    {% if task.state == "FAILURE" %}
      State: {{ task.state }}<BR>
      Reason: {{ task.result }}<BR>
    {% elif task.state == "INITIALIZE" %}
      State: {{ task.state }}<BR>
      Stage: {{ task.result.stage }} {{ task.result.i }}/{{task.result.total }}<BR>
    {% elif task.state == "PRELOADING" %}
      State: {{ task.state }}<BR>
      Stage: {{ task.result.stage }} {{ task.result.i }}/{{task.result.total }}<BR>
    {% elif task.state == "PROCESSING" %}
      State: {{ task.state }}<BR>
      Stage: {{ task.result.stage }} {{ task.result.i }}/{{task.result.total }}<BR>
      {% if task.result.stage == "update" or task.result.stage == "color_update" %}
      Image: {{ task.result.image }}/{{task.result.images }}
      {% endif %}
    {% else %}
      State: {{ task.state }}<BR>
      Result: {{ task.result }}<BR>
    {% endif %}
    
    </div>
    {% endblock %}
    
  9. Add any models you will need to the newly created models.py (uncommon)

  10. Edit voxel_globe/main/templates/main/html/index.html and add the new url to the main page

    <li><a href="{% url '{app_name}:make_order' %}">Order {App Name}</a></li>
    
  11. Finally, edit vip/settings.py and add voxel_globe.{app_name} to INSTALLED_APPS

  12. Restart the httpd daemon

Adding Processing Task

  1. Create voxel_globe/{app_name}/__init__.py

  2. Create and edit voxel_globe/{app_name}/tasks.py, for example

     import os
     from os import environ as env
    
     from celery.utils.log import get_task_logger
     logger = get_task_logger(__name__)
     import logging
    
     from voxel_globe.common_tasks import shared_task, VipTask
    
     @shared_task(base=VipTask, bind=True)
     def {task_name}(self, voxel_world_id, prob=0.5, ,
                           history=None):
       pass
    
  3. Finally, edit vip/settings.py and add voxel_globe.{app_name} to INSTALLED_APPS

  4. Restart celery workers

Advance celery routing

TODO

⚠️ **GitHub.com Fallback** ⚠️