Skip to content

Commit

Permalink
rest apis
Browse files Browse the repository at this point in the history
  • Loading branch information
nicokant committed Apr 24, 2024
1 parent 20838bf commit 8816ef6
Show file tree
Hide file tree
Showing 12 changed files with 257 additions and 5 deletions.
2 changes: 1 addition & 1 deletion config/api.py
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
from ninja import NinjaAPI

from metadata_catalogue.maps.api import maps_router
from metadata_catalogue.maps.apis import maps_router

api = NinjaAPI()

Expand Down
19 changes: 19 additions & 0 deletions config/routers.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,19 @@
from django.urls import path
from drf_spectacular.views import SpectacularAPIView, SpectacularRedocView, SpectacularSwaggerView
from rest_framework import routers

from metadata_catalogue.maps.api import views

router = routers.DefaultRouter()
router.register(r"maps", views.MapViewSet, basename="maps")
router.register(r"raster-sources", views.RasterSourceViewSet, basename="raster-sources")
router.register(r"vector-sources", views.VectorSourceViewSet, basename="vector-sources")
router.register(r"layers", views.LayerViewSet, basename="layers")
router.register(r"layer-groups", views.LayerGroupViewSet, basename="layer-groups")


urlpatterns = [
path("schema/", SpectacularAPIView.as_view(), name="schema"),
path("docs/", SpectacularSwaggerView.as_view(url_name="schema"), name="swagger-ui"),
path("docs/redoc/", SpectacularRedocView.as_view(url_name="schema"), name="redoc"),
] + router.urls
18 changes: 18 additions & 0 deletions config/settings/base.py
Original file line number Diff line number Diff line change
Expand Up @@ -92,6 +92,9 @@
"treebeard",
"corsheaders",
"rules.apps.AutodiscoverRulesConfig",
"rest_framework",
"rest_framework.authtoken",
"drf_spectacular",
]

LOCAL_APPS = [
Expand Down Expand Up @@ -347,3 +350,18 @@
CORS_ALLOW_CREDENTIALS = True

MAPS_API_KEY = env("MAPS_API_KEY", default=None)


REST_FRAMEWORK = {
"DEFAULT_PERMISSION_CLASSES": [
"rest_framework.permissions.IsAdminUser",
],
"DEFAULT_AUTHENTICATION_CLASSES": (
"rest_framework.authentication.BasicAuthentication",
"rest_framework.authentication.SessionAuthentication",
"rest_framework.authentication.TokenAuthentication",
),
"DEFAULT_SCHEMA_CLASS": "drf_spectacular.openapi.AutoSchema",
"DEFAULT_PAGINATION_CLASS": "rest_framework.pagination.LimitOffsetPagination",
"PAGE_SIZE": 50,
}
1 change: 1 addition & 0 deletions config/urls.py
Original file line number Diff line number Diff line change
Expand Up @@ -22,6 +22,7 @@
path("geoapi", landing_page),
path("geoapi/", include("metadata_catalogue.datasets.geoapi.urls", namespace="geoapi")),
path("datasets/", include("metadata_catalogue.datasets.urls")),
path("api/v1/", include("config.routers")),
path("api/", api.urls),
]

Expand Down
Empty file.
111 changes: 111 additions & 0 deletions metadata_catalogue/maps/api/serializers.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,111 @@
from rest_framework import serializers

from ..models import Layer, LayerGroup, Map, RasterSource, Source, VectorSource


class FileUploadSerializer(serializers.Serializer):
file = serializers.FileField(required=True)
field = serializers.CharField(required=True)


class MapSerializer(serializers.ModelSerializer):
class Meta:
model = Map
fields = [
"slug",
"id",
"title",
"subtitle",
"zoom",
"description",
"visibility",
"config",
"legend_config",
"basemap_config",
]


class RasterSourceBaseSerializer(serializers.ModelSerializer):
class Meta:
model = RasterSource
fields = [
"name",
"slug",
"extra",
"style",
"url",
"attribution",
"protocol",
]


class RasterSourceSerializer(serializers.ModelSerializer):
class Meta(RasterSourceBaseSerializer.Meta):
fields = [
"name",
"slug",
"extra",
"style",
"url",
"attribution",
"protocol",
"source",
"original_data",
]


class VectorSourceSerializer(serializers.ModelSerializer):
class Meta:
model = VectorSource
fields = [
"name",
"slug",
"extra",
"style",
"url",
"attribution",
"protocol",
"source",
"original_data",
"default_layer",
]


class LayerSerializer(serializers.ModelSerializer):
map = serializers.SlugRelatedField(slug_field="slug", queryset=Map.objects.all())
source = serializers.SlugRelatedField(slug_field="slug", queryset=Source.objects.all())

class Meta:
model = Layer
fields = [
"name",
"slug",
"map",
"source",
"style",
"group",
"group_order",
"downloadable",
"description",
"link",
"legend",
"is_basemap",
"is_lazy",
"hidden",
]


class LayerGroupSerializer(serializers.ModelSerializer):
map = serializers.SlugRelatedField(slug_field="slug", queryset=Map.objects.all(), allow_null=True)
parent = serializers.SlugRelatedField(slug_field="slug", queryset=LayerGroup.objects.all(), allow_null=True)

class Meta:
model = LayerGroup
fields = ["name", "order", "slug", "map", "description", "link", "download_url", "parent"]

def create(self, validated_data):
parent = validated_data.pop("parent")
if parent:
return parent.add_child(**validated_data)
else:
return LayerGroup.add_root(**validated_data)
75 changes: 75 additions & 0 deletions metadata_catalogue/maps/api/views.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,75 @@
from drf_spectacular.utils import extend_schema
from rest_framework import viewsets
from rest_framework.decorators import action
from rest_framework.parsers import MultiPartParser

from ..models import Layer, LayerGroup, Map, RasterSource, VectorSource
from .serializers import (
FileUploadSerializer,
LayerGroupSerializer,
LayerSerializer,
MapSerializer,
RasterSourceSerializer,
VectorSourceSerializer,
)


class MapViewSet(viewsets.ModelViewSet):
queryset = Map.objects.all()
serializer_class = MapSerializer
lookup_field = "slug"


UPLOAD_REQUEST_SCHEMA = {
"multipart/form-data": {
"type": "object",
"properties": {"field": {"type": "string"}, "file": {"type": "string", "format": "binary"}},
}
}


class UploadableMixin:
@action(detail=True, methods=["post"], parser_classes=(MultiPartParser,), serializer_class=FileUploadSerializer)
def upload(self, request):
instance = self.get_object()
serializer = self.get_serializer(data=request.data)
serializer.is_valid(raise_exception=True)
file = request.FILES.get("file")
field = serializer.validated_data.get("field")
setattr(instance, field, file)
instance.save()
return instance


class RasterSourceViewSet(UploadableMixin, viewsets.ModelViewSet):
queryset = RasterSource.objects.all()
lookup_field = "slug"
serializer_class = RasterSourceSerializer

@extend_schema(request=UPLOAD_REQUEST_SCHEMA, responses={"200": RasterSourceSerializer})
@action(detail=True, methods=["post"], parser_classes=(MultiPartParser,), serializer_class=FileUploadSerializer)
def upload(self, request):
return super().upload(request)


class VectorSourceViewSet(UploadableMixin, viewsets.ModelViewSet):
queryset = VectorSource.objects.all()
serializer_class = VectorSourceSerializer
lookup_field = "slug"

@extend_schema(request=UPLOAD_REQUEST_SCHEMA, responses={"200": RasterSourceSerializer})
@action(detail=True, methods=["post"], parser_classes=(MultiPartParser,), serializer_class=FileUploadSerializer)
def upload(self, request):
return super().upload(request)


class LayerViewSet(viewsets.ModelViewSet):
queryset = Layer.objects.all()
serializer_class = LayerSerializer
lookup_field = "slug"


class LayerGroupViewSet(viewsets.ModelViewSet):
queryset = LayerGroup.objects.all()
serializer_class = LayerGroupSerializer
lookup_field = "slug"
File renamed without changes.
Original file line number Diff line number Diff line change
@@ -0,0 +1,21 @@
# Generated by Django 4.2.8 on 2024-04-24 11:25

from django.db import migrations, models


class Migration(migrations.Migration):
dependencies = [
("maps", "0013_layer_hidden_layer_is_lazy"),
]

operations = [
migrations.AddField(
model_name="layergroup",
name="slug",
field=models.SlugField(blank=True, max_length=250, null=True),
),
migrations.AddConstraint(
model_name="layergroup",
constraint=models.UniqueConstraint(models.F("slug"), name="group unique slug"),
),
]
11 changes: 8 additions & 3 deletions metadata_catalogue/maps/models.py
Original file line number Diff line number Diff line change
Expand Up @@ -3,6 +3,7 @@
from django.conf import settings
from django.db import models
from django.urls import reverse
from django_lifecycle import BEFORE_CREATE, LifecycleModel, hook
from polymorphic.models import PolymorphicModel
from slugify import slugify
from treebeard.mp_tree import MP_Node
Expand Down Expand Up @@ -149,7 +150,7 @@ class Meta:
]


class Map(models.Model):
class Map(LifecycleModel):
title = models.CharField(max_length=150)
slug = models.SlugField(null=True, blank=True, max_length=150)
subtitle = models.CharField(max_length=250, null=True, blank=True)
Expand All @@ -164,10 +165,10 @@ class Map(models.Model):
basemap_config = models.JSONField(null=True, blank=True)
config = models.JSONField(null=True, blank=True)

def save(self, *args, **kwargs):
@hook(BEFORE_CREATE)
def generate_slug(self, *args, **kwargs):
if self.slug is None:
self.slug = slugify(self.title)
super().save(*args, **kwargs)

def __str__(self):
return self.title
Expand Down Expand Up @@ -286,6 +287,7 @@ def get_style(self, request):

class LayerGroup(MP_Node):
name = models.CharField(max_length=150)
slug = models.SlugField(null=True, blank=True, max_length=250)
order = models.IntegerField(default=0, blank=True)
map = models.ForeignKey("maps.Map", on_delete=models.CASCADE, null=True, blank=True, related_name="groups")
download_url = models.URLField(null=True, blank=True)
Expand All @@ -294,6 +296,9 @@ class LayerGroup(MP_Node):

node_order_by = ["order", "name"]

class Meta:
constraints = [models.UniqueConstraint("slug", name="group unique slug")]

def __str__(self):
return f"{self.name} @ {self.map}"

Expand Down
2 changes: 1 addition & 1 deletion metadata_catalogue/maps/urls.py
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
from ninja import NinjaAPI

from .api import maps_router
from .apis import maps_router

api = NinjaAPI()
api.add_router("/maps/", maps_router)
2 changes: 2 additions & 0 deletions pyproject.toml
Original file line number Diff line number Diff line change
Expand Up @@ -169,6 +169,8 @@ dependencies = [
"django-appconf>=1.0.6",
"django-cors-headers>=4.3.1",
"rules>=3.3",
"django-rest-framework>=0.1.0",
"drf-spectacular>=0.27.2",
]
requires-python = ">=3.10"
name = ""
Expand Down

0 comments on commit 8816ef6

Please sign in to comment.