Creating a New Django App - VisionSystemsInc/voxel_globe GitHub Wiki
Here is how to create a new app with a form, with an endpoint to handle the form submission, an html template,
-
./just manage startapp {app_name}
-
Edit
voxel_globe/vip/urls.py
, add a newurl
to theurlpatterns
tuple -
Add the url entry
url(r'^apps/{app_name}/', include('voxel_globe.{app_name}.urls', namespace='{app_name}')),
-
Create and edit
voxel_globe/{app_name}/urls.py
to contain the new django endpoints, typicallyfrom django.conf.urls import url import voxel_globe.{app_name}.views as views urlpatterns = [ url(r'^$', views.{my_page}, name='{my_page_name}'), ]
-
Edit
voxel_globe/{app_name}/views.py
, typically
from django.shortcuts import render, redirect
def {my_page}(request):
return render(request, '{app_name}/html/{my_page}.html',
{'title': 'Voxel Globe - {App Title here}',
'page_title': 'Voxel Globe - {App Page Title here}'})
- Create and edit
voxel_globe/{app_name}/templates/{app_name}/html/{my_page}.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">
<h1>hi</h1>
</div>
{% endblock %}
- Optionally, edit
main/templates/main/html/index.html
to include a main-page link to first page of the new app. Something, perhaps, like:
<li><a href="{% url '{app_name}:{view}' %}">Application Name</a></li>
- Finally, edit
vip/settings.py
and addvoxel_globe.{app_name}
toINSTALLED_APPS
- Restart the uwsgi and asgi daemon
- Edit
voxel_globe/{app_name}/tests.py
to contain the units tests, typically
from django.test import TestCase
from voxel_globe.common_tests import VoxelGlobeTestCase
#optionally
from django.urls import reverse
from voxel_globe.tools.django import partial_reverse
class Vip{appname}TestCase(VoxelGlobeTestCase):
def setUp(self):
self.client = self.setupVoxelGlobeTestCase()
def test_{test_name}(self):
r = self.client.post(reverse('{appname}:{view_url_name}'),
data='{}', #example json data
content_type="application/json")
r = self.client.post(partial_reverse('{appname}:{view_url_name}')+'{rest_of_partial_url}',
data='77', #example data
content_type="application/json")
See here for more information on Django unit tests. The test class inherits from unittest.TestCase
Here is an example form just to give you an idea
- Create and edit
voxel_globe/{app_name}/forms.py
to add the 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').order_by('name'))
- Edit
voxel_globe/{app_name}/views.py
, typically
def {my_form}(request):
auto_open = False
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,))
auto_open = True
else:
form = {AppName}Form()
return render(request, '{app_name}/html/my_form.html',
{'title': 'Voxel Globe - {App Title here}',
'page_title': 'Voxel Globe - {App Page Title here}',
'form':form, 'task_menu_auto_open': auto_open})
- Create and edit
voxel_globe/{app_name}/templates/{app_name}/html/my_form.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}:{my_form_name}' %}" method="post">
{% csrf_token %}
<table>
{{ form.as_table }}
</table>
<input type="submit" value="Submit" />
</form>
</div>
{% endblock %}
-
Add the new url to
voxel_globe/{app_name}/urls.py
url(r'^$', views.{my_form}, name='{my_form_name}'),
By default, all tasks use voxel_globe/task/templates/task/html/{app_name}_tasks_{task_name}.html
for status, and if that does not exist, it defaults to the voxel_globe/task/templates/task/html/default_status.html
page. To write a custom status page, create and edit voxel_globe/task/templates/task/html/{app_name}_tasks_{task_name}.html
to include
{% extends "main/common_header.html" %}
{% load staticfiles %}
The following blocks can be defined to have a custom task status
-
task_info
- The Task info display at the top of the status block -
failure
- Used whentask.state == "Failure"
-
revoked
- Used whentask.state == "Revoked"
-
success
- Used whentask.state == "Success"
-
task_specific
- Used for all othertask.state
s- If results dictionary contains the keys
index
andtotal
, a progress bar is used to show the status
- If results dictionary contains the keys
-
Create and edit
voxel_globe/{app_name}/templates/{app_name}/html/order_status.html
, for example{% extends "task/html/default_status.html" %} {% block task_info %} Task ID: {{ task.task_id }}<BR> {% endblock %} {% block failure %} State: {{ task.state }}<BR> Reason: {{ task.result }}<BR> {% endblock %} {% block task_specific %} {% if 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 %} {% endblock %}
- Add any models you will need to the newly created
models.py
(uncommon)
-
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>
-
Create
voxel_globe/{app_name}/__init__.py
-
Create and edit
voxel_globe/{app_name}/tasks.py
, for exampleimport 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): pass
-
Finally, edit
vip/settings.py
and addvoxel_globe.{app_name}
toINSTALLED_APPS
-
Restart celery workers
It's really easy to route a task to a specific key.
@shared_task(base=VipTask, bind=True, routing_key="gpu")