Project tiles.json almost working

pull/50/head
Piero Toffanin 2016-11-15 15:55:48 -05:00
rodzic 23f65bf9cd
commit e3fa5470ed
6 zmienionych plików z 67 dodań i 29 usunięć

31
app/api/common.py 100644
Wyświetl plik

@ -0,0 +1,31 @@
from django.core.exceptions import ObjectDoesNotExist
from rest_framework import exceptions
from app import models
def get_and_check_project(request, project_pk, perms=('view_project',)):
'''
Retrieves a project and raises an exeption if the current user
has no access to it.
'''
try:
project = models.Project.objects.get(pk=project_pk, deleting=False)
for perm in perms:
if not request.user.has_perm(perm, project): raise ObjectDoesNotExist()
except ObjectDoesNotExist:
raise exceptions.NotFound()
return project
def get_tiles_json(name, tiles, bounds):
return {
'tilejson': '2.1.0',
'name': name,
'version': '1.0.0',
'scheme': 'tms',
'tiles': tiles,
'minzoom': 0,
'maxzoom': 22,
'bounds': bounds
}

Wyświetl plik

@ -1,8 +1,13 @@
from django.contrib.auth.models import User
from django.contrib.gis.db.models.functions import Envelope
from rest_framework import serializers, viewsets
from rest_framework.generics import get_object_or_404
from rest_framework.response import Response
from rest_framework.views import APIView
from django.contrib.gis.db.models import Extent
from app import models
from .tasks import TaskIDsSerializer
from .common import get_and_check_project, get_tiles_json
class ProjectSerializer(serializers.ModelSerializer):
@ -29,4 +34,25 @@ class ProjectViewSet(viewsets.ModelViewSet):
filter_fields = ('id', 'name', 'description', 'created_at')
serializer_class = ProjectSerializer
queryset = models.Project.objects.filter(deleting=False)
ordering_fields = '__all__'
ordering_fields = '__all__'
class ProjectTilesJson(APIView):
queryset = models.Project.objects.filter(deleting=False)
def get(self, request, pk=None):
"""
Returns a tiles.json file for consumption by a client
"""
project = get_and_check_project(request, pk)
task_ids = [task.id for task in project.tasks()]
extent = [0, 0, 0, 0] # TODO! world extent
if len(task_ids) > 0:
# Extent of all orthophotos of all tasks for this project
extent = project.task_set.only('geom').annotate(geom=Envelope('orthophoto')).aggregate(Extent('geom'))['geom__extent']
json = get_tiles_json(project.name, [
'/api/projects/{}/tasks/{}/tiles/{{z}}/{{x}}/{{y}}.png'.format(project.id, task_id) for task_id in task_ids
], extent)
return Response(json)

Wyświetl plik

@ -8,6 +8,7 @@ from rest_framework import status, serializers, viewsets, filters, exceptions, p
from rest_framework.response import Response
from rest_framework.decorators import detail_route
from rest_framework.views import APIView
from .common import get_and_check_project, get_tiles_json
from app import models, scheduler, pending_actions
from nodeodm.models import ProcessingNode
@ -31,20 +32,6 @@ class TaskSerializer(serializers.ModelSerializer):
exclude = ('processing_lock', 'console_output', 'orthophoto', )
def get_and_check_project(request, project_pk, perms=('view_project',)):
'''
Retrieves a project and raises an exeption if the current user
has no access to it.
'''
try:
project = models.Project.objects.get(pk=project_pk)
for perm in perms:
if not request.user.has_perm(perm, project): raise ObjectDoesNotExist()
except ObjectDoesNotExist:
raise exceptions.NotFound()
return project
class TaskViewSet(viewsets.ViewSet):
"""
A task represents a set of images and other input to be sent to a processing node.
@ -189,18 +176,9 @@ class TaskTilesJson(TaskNestedView):
Returns a tiles.json file for consumption by a client
"""
task = self.get_and_check_task(request, pk, project_pk)
json = {
'tilejson': '2.1.0',
'name': task.name,
'version': '1.0.0',
'scheme': 'tms',
'tiles': [
json = get_tiles_json(task.name, [
'/api/projects/{}/tasks/{}/tiles/{{z}}/{{x}}/{{y}}.png'.format(task.project.id, task.id)
],
'minzoom': 0,
'maxzoom': 22,
'bounds': task.orthophoto.extent
}
], task.orthophoto.extent)
return Response(json)

Wyświetl plik

@ -1,5 +1,5 @@
from django.conf.urls import url, include
from .projects import ProjectViewSet
from .projects import ProjectViewSet, ProjectTilesJson
from .tasks import TaskViewSet, TaskTiles, TaskTilesJson, TaskAssets
from .processingnodes import ProcessingNodeViewSet
from rest_framework_nested import routers
@ -15,6 +15,8 @@ urlpatterns = [
url(r'^', include(router.urls)),
url(r'^', include(tasks_router.urls)),
url(r'projects/(?P<pk>[^/.]+)/tiles\.json$', ProjectTilesJson.as_view()),
url(r'projects/(?P<project_pk>[^/.]+)/tasks/(?P<pk>[^/.]+)/tiles/(?P<z>[\d]+)/(?P<x>[\d]+)/(?P<y>[\d]+)\.png$', TaskTiles.as_view()),
url(r'projects/(?P<project_pk>[^/.]+)/tasks/(?P<pk>[^/.]+)/tiles\.json$', TaskTilesJson.as_view()),
url(r'projects/(?P<project_pk>[^/.]+)/tasks/(?P<pk>[^/.]+)/download/(?P<asset>[^/.]+)/$', TaskAssets.as_view()),

Wyświetl plik

@ -61,7 +61,7 @@ class Project(models.Model):
def __str__(self):
return self.name
def tasks(self, pk=None):
def tasks(self):
return self.task_set.only('id')
class Meta:

Wyświetl plik

@ -197,6 +197,7 @@ class TestApi(BootTestCase):
# - tiles API urls (permissions, 404s)
# - assets download
# - project deletion
# - project tiles API urls
def test_processingnodes(self):
client = APIClient()