OpenDroneMap-WebODM/app/models.py

118 wiersze
4.8 KiB
Python
Czysty Zwykły widok Historia

2016-09-21 20:04:47 +00:00
from __future__ import unicode_literals
2016-08-10 20:23:17 +00:00
from django.db import models
from django.db.models import signals
2016-09-09 21:37:04 +00:00
from django.utils import timezone
from django.contrib.auth.models import User
2016-09-10 15:24:16 +00:00
from django.contrib.postgres import fields
2016-09-21 20:04:47 +00:00
from nodeodm.models import ProcessingNode
from django.dispatch import receiver
from guardian.shortcuts import get_perms_for_model, assign_perm
from guardian.models import UserObjectPermissionBase
from guardian.models import GroupObjectPermissionBase
from django.db import transaction
2016-09-10 15:24:16 +00:00
def assets_directory_path(taskId, projectId, filename):
# files will be uploaded to MEDIA_ROOT/project/<id>/task/<id>/<filename>
return 'project/{0}/task/{1}/{2}'.format(projectId, taskId, filename)
2016-09-10 15:24:16 +00:00
2016-09-09 21:37:04 +00:00
class Project(models.Model):
owner = models.ForeignKey(User, on_delete=models.PROTECT, help_text="The person who created the project")
name = models.CharField(max_length=255, help_text="A label used to describe the project")
description = models.TextField(null=True, blank=True, help_text="More in-depth description of the project")
2016-09-09 21:37:04 +00:00
created_at = models.DateTimeField(default=timezone.now, help_text="Creation date")
def __str__(self):
return self.name
def tasks(self, pk=None):
return Task.objects.filter(project=self);
class Meta:
permissions = (
('view_project', 'Can view project'),
)
@receiver(signals.post_save, sender=Project, dispatch_uid="project_post_save")
def project_post_save(sender, instance, created, **kwargs):
"""
Automatically assigns all permissions to the owner. If the owner changes
it's up to the user/developer to remove the previous owner's permissions.
"""
for perm in get_perms_for_model(sender).all():
assign_perm(perm.codename, instance.owner, instance)
class ProjectUserObjectPermission(UserObjectPermissionBase):
content_object = models.ForeignKey(Project)
class ProjectGroupObjectPermission(GroupObjectPermissionBase):
content_object = models.ForeignKey(Project)
2016-09-10 15:24:16 +00:00
def gcp_directory_path(task, filename):
return assets_directory_path(task.id, task.project.id, filename)
2016-09-09 21:37:04 +00:00
class Task(models.Model):
2016-09-10 15:24:16 +00:00
STATUS_CODES = (
(10, 'QUEUED'),
(20, 'RUNNING'),
(30, 'FAILED'),
(40, 'COMPLETED'),
(50, 'CANCELED')
)
uuid = models.CharField(max_length=255, null=True, blank=True, help_text="Identifier of the task (as returned by OpenDroneMap's REST API)")
2016-09-10 15:24:16 +00:00
project = models.ForeignKey(Project, on_delete=models.CASCADE, help_text="Project that this task belongs to")
name = models.CharField(max_length=255, null=True, blank=True, help_text="A label for the task")
2016-09-09 21:37:04 +00:00
processing_time = models.IntegerField(default=-1, help_text="Number of milliseconds that elapsed since the beginning of this task (-1 indicates that no information is available)")
processing_node = models.ForeignKey(ProcessingNode, null=True, blank=True, help_text="Processing node assigned to this task (or null if this task has not been associated yet)")
status = models.IntegerField(choices=STATUS_CODES, null=True, blank=True, help_text="Current status of the task")
options = fields.JSONField(default=dict(), blank=True, help_text="Options that are being used to process this task")
console_output = models.TextField(null=True, blank=True, help_text="Console output of the OpenDroneMap's process")
ground_control_points = models.FileField(null=True, blank=True, upload_to=gcp_directory_path, help_text="Optional Ground Control Points file to use for processing")
2016-09-09 21:37:04 +00:00
# georeferenced_model
# orthophoto
# textured_model
# mission
created_at = models.DateTimeField(default=timezone.now, help_text="Creation date")
2016-08-10 20:23:17 +00:00
2016-09-09 21:37:04 +00:00
def __str__(self):
return 'Task ID: {}'.format(self.id)
@staticmethod
def create_from_images(images, project):
'''
Create a new task from a set of input images (such as the ones coming from request.FILES).
This will happen inside a transaction so if one of the images
fails to load, the task will not be created.
'''
with transaction.atomic():
task = Task.objects.create(project=project)
for image in images:
ImageUpload.objects.create(task=task, image=image)
return task
# In case of error
return None
2016-09-10 15:24:16 +00:00
class Meta:
permissions = (
('view_task', 'Can view task'),
)
2016-09-10 15:24:16 +00:00
def image_directory_path(imageUpload, filename):
2016-09-10 15:24:16 +00:00
return assets_directory_path(imageUpload.task.id, imageUpload.task.project.id, filename)
class ImageUpload(models.Model):
task = models.ForeignKey(Task, on_delete=models.CASCADE, help_text="Task this image belongs to")
image = models.ImageField(upload_to=image_directory_path, help_text="File uploaded by a user")
def __str__(self):
return self.image.name