Skip to content

Commit

Permalink
Merge pull request #86 from OpenGeoscience/remove-derived-regions
Browse files Browse the repository at this point in the history
Remove Derived Regions
  • Loading branch information
jjnesbitt authored Nov 7, 2024
2 parents 8a09d59 + c85cc6a commit 8b1b5d0
Show file tree
Hide file tree
Showing 21 changed files with 49 additions and 520 deletions.
12 changes: 0 additions & 12 deletions uvdat/core/admin.py
Original file line number Diff line number Diff line change
Expand Up @@ -3,7 +3,6 @@
from uvdat.core.models import (
Chart,
Dataset,
DerivedRegion,
FileItem,
Network,
NetworkEdge,
Expand Down Expand Up @@ -71,16 +70,6 @@ def get_dataset_name(self, obj):
return obj.dataset.name


class DerivedRegionAdmin(admin.ModelAdmin):
list_display = ['id', 'name', 'get_project_name', 'operation', 'get_source_region_names']

def get_project_name(self, obj):
return obj.project.name

def get_source_region_names(self, obj):
return ', '.join(r.name for r in obj.source_regions.all())


class NetworkAdmin(admin.ModelAdmin):
list_display = ['id', 'category', 'get_dataset_name']

Expand Down Expand Up @@ -123,7 +112,6 @@ class SimulationResultAdmin(admin.ModelAdmin):
admin.site.register(VectorMapLayer, VectorMapLayerAdmin)
admin.site.register(VectorFeature, VectorFeatureAdmin)
admin.site.register(SourceRegion, SourceRegionAdmin)
admin.site.register(DerivedRegion, DerivedRegionAdmin)
admin.site.register(Network, NetworkAdmin)
admin.site.register(NetworkNode, NetworkNodeAdmin)
admin.site.register(NetworkEdge, NetworkEdgeAdmin)
Expand Down
15 changes: 15 additions & 0 deletions uvdat/core/migrations/0007_delete_derivedregion.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,15 @@
# Generated by Django 5.0.7 on 2024-10-28 20:58

from django.db import migrations


class Migration(migrations.Migration):
dependencies = [
('core', '0006_alter_project_default_map_zoom'),
]

operations = [
migrations.DeleteModel(
name='DerivedRegion',
),
]
3 changes: 1 addition & 2 deletions uvdat/core/models/__init__.py
Original file line number Diff line number Diff line change
Expand Up @@ -4,7 +4,7 @@
from .map_layers import RasterMapLayer, VectorFeature, VectorMapLayer
from .networks import Network, NetworkEdge, NetworkNode
from .project import Project
from .regions import DerivedRegion, SourceRegion
from .regions import SourceRegion
from .simulations import SimulationResult

__all__ = [
Expand All @@ -16,7 +16,6 @@
VectorMapLayer,
VectorFeature,
SourceRegion,
DerivedRegion,
Network,
NetworkEdge,
NetworkNode,
Expand Down
41 changes: 0 additions & 41 deletions uvdat/core/models/regions.py
Original file line number Diff line number Diff line change
Expand Up @@ -2,8 +2,6 @@
from django.db import models

from .dataset import Dataset
from .map_layers import VectorMapLayer
from .project import Project


class SourceRegion(models.Model):
Expand All @@ -17,42 +15,3 @@ class Meta:
# We enforce name uniqueness across datasets
models.UniqueConstraint(name='unique-source-region-name', fields=['dataset', 'name'])
]


class DerivedRegion(models.Model):
class VectorOperation(models.TextChoices):
UNION = 'UNION', 'Union'
INTERSECTION = 'INTERSECTION', 'Intersection'

name = models.CharField(max_length=255)
project = models.ForeignKey(
Project, on_delete=models.CASCADE, related_name='derived_regions', null=True
)
metadata = models.JSONField(blank=True, null=True)
boundary = geo_models.MultiPolygonField()

# Data from the source regions
source_regions = models.ManyToManyField(SourceRegion, related_name='derived_regions')
operation = models.CharField(
max_length=max(len(choice[0]) for choice in VectorOperation.choices),
choices=VectorOperation.choices,
)

# Since these regions are not associated with Datasets,
# They need their own reference to a map representation
map_layer = models.ForeignKey(VectorMapLayer, on_delete=models.PROTECT)

def get_map_layers(self):
return [
{
'id': self.map_layer.id,
'index': 0,
'type': 'vector',
}
]

class Meta:
constraints = [
# We enforce name uniqueness across projects
models.UniqueConstraint(name='unique-derived-region-name', fields=['project', 'name'])
]
3 changes: 1 addition & 2 deletions uvdat/core/rest/__init__.py
Original file line number Diff line number Diff line change
Expand Up @@ -4,7 +4,7 @@
from .map_layers import RasterMapLayerViewSet, VectorMapLayerViewSet
from .network import NetworkEdgeViewSet, NetworkNodeViewSet, NetworkViewSet
from .project import ProjectViewSet
from .regions import DerivedRegionViewSet, SourceRegionViewSet
from .regions import SourceRegionViewSet
from .simulations import SimulationViewSet
from .user import UserViewSet

Expand All @@ -19,7 +19,6 @@
NetworkEdgeViewSet,
DatasetViewSet,
SourceRegionViewSet,
DerivedRegionViewSet,
SimulationViewSet,
UserViewSet,
]
2 changes: 1 addition & 1 deletion uvdat/core/rest/access_control.py
Original file line number Diff line number Diff line change
Expand Up @@ -13,7 +13,7 @@ def filter_queryset_by_projects(queryset: QuerySet[Model], projects: QuerySet[mo
model = queryset.model
if model == models.Project:
return queryset.filter(id__in=projects.values_list('id', flat=True))
if model in [models.Dataset, models.Chart, models.DerivedRegion, models.SimulationResult]:
if model in [models.Dataset, models.Chart, models.SimulationResult]:
return queryset.filter(project__in=projects)
if model in [
models.FileItem,
Expand Down
6 changes: 0 additions & 6 deletions uvdat/core/rest/project.py
Original file line number Diff line number Diff line change
Expand Up @@ -42,12 +42,6 @@ def permissions(self, request: Request, *args: Any, **kwargs: Any):

return Response(ProjectSerializer(project).data, status=200)

@action(detail=True, methods=['get'])
def regions(self, request, **kwargs):
project = self.get_object()
regions = project.derived_regions.all()
return HttpResponse(regions, status=200)

@action(detail=True, methods=['get'])
def simulation_results(self, request, **kwargs):
project = self.get_object()
Expand Down
69 changes: 4 additions & 65 deletions uvdat/core/rest/regions.py
Original file line number Diff line number Diff line change
@@ -1,20 +1,10 @@
import json
from rest_framework import mixins
from rest_framework.viewsets import GenericViewSet

from django.http import HttpResponse
from drf_yasg.utils import swagger_auto_schema
from rest_framework.decorators import action
from rest_framework.viewsets import GenericViewSet, mixins

from uvdat.core.models import DerivedRegion, SourceRegion
from uvdat.core.models import SourceRegion
from uvdat.core.rest.access_control import GuardianFilter, GuardianPermission
from uvdat.core.tasks.regions import DerivedRegionCreationError, create_derived_region

from .serializers import (
DerivedRegionCreationSerializer,
DerivedRegionDetailSerializer,
DerivedRegionListSerializer,
SourceRegionSerializer,
)
from .serializers import SourceRegionSerializer


class SourceRegionViewSet(mixins.RetrieveModelMixin, mixins.ListModelMixin, GenericViewSet):
Expand All @@ -23,54 +13,3 @@ class SourceRegionViewSet(mixins.RetrieveModelMixin, mixins.ListModelMixin, Gene
permission_classes = [GuardianPermission]
filter_backends = [GuardianFilter]
lookup_field = 'id'


class DerivedRegionViewSet(mixins.RetrieveModelMixin, mixins.ListModelMixin, GenericViewSet):
queryset = DerivedRegion.objects.all()
serializer_class = DerivedRegionListSerializer
permission_classes = [GuardianPermission]
filter_backends = [GuardianFilter]
lookup_field = 'id'

def get_queryset(self):
qs = super().get_queryset()
project_id: str = self.request.query_params.get('project')
if project_id is None or not project_id.isdigit():
return qs

return qs.filter(project=int(project_id))

def get_serializer_class(self):
if self.detail:
return DerivedRegionDetailSerializer

return super().get_serializer_class()

@action(detail=True, methods=['GET'])
def as_feature(self, request, *args, **kwargs):
obj: DerivedRegion = self.get_object()
feature = {
'type': 'Feature',
'geometry': json.loads(obj.boundary.geojson),
'properties': DerivedRegionListSerializer(instance=obj).data,
}

return HttpResponse(json.dumps(feature))

@swagger_auto_schema(request_body=DerivedRegionCreationSerializer)
def create(self, request, *args, **kwargs):
serializer = DerivedRegionCreationSerializer(data=request.data)
serializer.is_valid(raise_exception=True)

try:
data = serializer.validated_data
derived_region = create_derived_region(
name=data['name'],
project=data['project'],
region_ids=data['regions'],
operation=data['operation'],
)
except DerivedRegionCreationError as e:
return HttpResponse(str(e), status=400)

return HttpResponse(DerivedRegionDetailSerializer(instance=derived_region).data, status=201)
60 changes: 0 additions & 60 deletions uvdat/core/rest/serializers.py
Original file line number Diff line number Diff line change
@@ -1,5 +1,3 @@
import json

from django.contrib.auth.models import User
from django.contrib.gis.geos import Point
from django.contrib.gis.serializers import geojson
Expand All @@ -9,7 +7,6 @@
from uvdat.core.models import (
Chart,
Dataset,
DerivedRegion,
FileItem,
Network,
NetworkEdge,
Expand Down Expand Up @@ -76,7 +73,6 @@ def get_followers(self, obj):
def get_item_counts(self, obj):
return {
'datasets': obj.datasets.count(),
'regions': obj.derived_regions.count(),
'charts': obj.charts.count(),
'simulations': obj.simulation_results.count(),
}
Expand Down Expand Up @@ -167,14 +163,6 @@ class Meta:


class VectorMapLayerDetailSerializer(VectorMapLayerSerializer):
derived_region_id = serializers.SerializerMethodField('get_derived_region_id')

def get_derived_region_id(self, obj):
dr = obj.derivedregion_set.first()
if dr is None:
return None
return dr.id

class Meta:
model = VectorMapLayer
exclude = ['geojson_file']
Expand All @@ -195,54 +183,6 @@ def get_dump_object(self, obj):
return val


class DerivedRegionListSerializer(serializers.ModelSerializer):
map_layers = serializers.SerializerMethodField('get_map_layers')

def get_map_layers(self, obj):
return obj.get_map_layers()

class Meta:
model = DerivedRegion
fields = [
'id',
'name',
'project',
'metadata',
'source_regions',
'operation',
'map_layers',
]


class DerivedRegionDetailSerializer(serializers.ModelSerializer):
class Meta:
model = DerivedRegion
fields = '__all__'

boundary = serializers.SerializerMethodField()
map_layers = serializers.SerializerMethodField('get_map_layers')

def get_boundary(self, obj):
return json.loads(obj.boundary.geojson)

def get_map_layers(self, obj):
return obj.get_map_layers()


class DerivedRegionCreationSerializer(serializers.ModelSerializer):
class Meta:
model = DerivedRegion
fields = [
'name',
'project',
'regions',
'operation',
]

regions = serializers.ListField(child=serializers.IntegerField())
operation = serializers.ChoiceField(choices=DerivedRegion.VectorOperation.choices)


class NetworkSerializer(serializers.ModelSerializer):
class Meta:
model = Network
Expand Down
Loading

0 comments on commit 8b1b5d0

Please sign in to comment.