Skip to content

Commit

Permalink
Merge pull request #39 from catalpainternational/feature/geojson-pyda…
Browse files Browse the repository at this point in the history
…ntic

Initial support for `geojson-pydantic`
  • Loading branch information
joshbrooks authored May 22, 2023
2 parents e023600 + a1ec991 commit 45d0363
Show file tree
Hide file tree
Showing 11 changed files with 304 additions and 332 deletions.
554 changes: 280 additions & 274 deletions poetry.lock

Large diffs are not rendered by default.

7 changes: 6 additions & 1 deletion pyproject.toml
Original file line number Diff line number Diff line change
Expand Up @@ -17,6 +17,10 @@ exclude = '''
)/
'''

[tool.ruff]
line-length = 119
exclude = ['migrations']

[tool.poetry]
name = "simple-locations"
version = "4.0.0"
Expand All @@ -36,9 +40,10 @@ homepage = "https://github.com/catalpainternational/simple_locations"
[tool.poetry.dependencies]
python = "^3.8"
django-mptt = "^0.14.0"
pydantic = "^1.10.6"
pydantic = ">1.10.6,<2"
django-ninja = "^0.21.0"
django-geojson = "^4.0.0"
geojson-pydantic = "^0.6.2"

[tool.poetry.group.dev]
optional = true
Expand Down
4 changes: 2 additions & 2 deletions simple_locations/feature_manager.py
Original file line number Diff line number Diff line change
@@ -1,9 +1,9 @@
from typing import Generator, Union

from django.db import models
from geojson_pydantic import FeatureCollection, Feature

from simple_locations.gis_functions import JsonFeature
from simple_locations.schemas import Feature, FeatureCollection


class FeatureQueryset(models.QuerySet):
Expand All @@ -30,7 +30,7 @@ def to_featurecollection(
>>> [Feature.parse_obj(i) for i in Area.geofunctions.filter(kind__name='district').to_features(simplify=1e-3, quantize=5).values_list('feature', flat=True)]
>>> # A FeatureCollection:
>>> FeatureCollection.parse_obj(queryset.aggregate(features = JSONBAgg(JsonFeature())))
"""
""" # noqa: E501
return FeatureCollection.construct(features=[*self.to_features(simplify=simplify, quantize=quantize)])

def annotate_features(self, simplify: Union[float, None] = None, quantize: Union[int, None] = None):
Expand Down
1 change: 1 addition & 0 deletions simple_locations/gis_functions.py
Original file line number Diff line number Diff line change
Expand Up @@ -103,6 +103,7 @@ def __init__(
g = Quantize(g, quantize=quantize)
if multi:
g = Multi(g)
expressions.extend((Value("type"), Value("Feature")))
expressions.extend((Value("geometry"), AsGeoJson(g, bbox=bbox_, crs=crs_, precision=precision_)))
expressions.extend((Value("properties"), JSONObject(**fields)))
super().__init__(*expressions)
2 changes: 1 addition & 1 deletion simple_locations/management/commands/create_borders.py
Original file line number Diff line number Diff line change
Expand Up @@ -105,7 +105,7 @@ class Scripts:
(select areas.area_ids from areas
where areas.border_id = b.id)
where b.id in (select border_id from areas)
"""
""" # noqa: E501

update_border_type_array = """
Expand Down
2 changes: 1 addition & 1 deletion simple_locations/management/commands/import_dird.py
Original file line number Diff line number Diff line change
Expand Up @@ -235,7 +235,7 @@ def perform_rename(self):
Wosera-Gawi District Wosera Gawi District
Yangoru-Saussia District Yangoru Saussia District"""

renames = [] # type: List[RenameDistrict]
renames: List[RenameDistrict] = []

for s in sources.split("\n"):
n = s.split("\t")
Expand Down
2 changes: 1 addition & 1 deletion simple_locations/manager.py
Original file line number Diff line number Diff line change
Expand Up @@ -33,7 +33,7 @@ def to_geojson(self, simplify: float = 1e-3, quantize: int = 5) -> str:
"""

output = io.StringIO() # Avoids a round-trip deserializer by using a raw StringIO
prefix = """{"type": "FeatureCollection", "crs": {"type": "name", "properties": {"name": "EPSG:4326"}}, "features": ["""
prefix = """{"type": "FeatureCollection", "crs": {"type": "name", "properties": {"name": "EPSG:4326"}}, "features": [""" # noqa: E501
pattern = '{"type": "Feature", "geometry": %s, "properties": {"id": %s } }'
suffix = "]}"

Expand Down
18 changes: 10 additions & 8 deletions simple_locations/router.py
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,9 @@

from ninja import Router

from simple_locations import model_schemas, models, schemas
from geojson_pydantic import FeatureCollection, Feature

from simple_locations import model_schemas, models

router = Router(tags=["SimpleLocations"])

Expand All @@ -25,17 +27,17 @@ def area_type_list(request):
return models.AreaType.objects.all()


@router.get("/area/by-id/{area_id}.geojson", response=schemas.Feature)
@router.get("/area/by-id/{area_id}.geojson", response=Feature)
def area_id(request, area_id: int):
"""
Returns the geometry of a single Area
as a single GeoJSON Feature
"""
features: Generator[schemas.Feature, None, None] = models.Area.features.filter(pk=area_id).to_features()
return schemas.Feature.parse_obj(next(features))
features: Generator[Feature, None, None] = models.Area.features.filter(pk=area_id).to_features()
return Feature.parse_obj(next(features))


@router.get("/area/by-parent/{area_id}-s{simplify}-q{quantize}.geojson", response=schemas.FeatureCollection)
@router.get("/area/by-parent/{area_id}-s{simplify}-q{quantize}.geojson", response=FeatureCollection)
def area_children_compressed(request, area_id: int, simplify: int, quantize: int):
"""
Returns the direct descendants of a given Area as a FeatureCollection
Expand All @@ -46,7 +48,7 @@ def area_children_compressed(request, area_id: int, simplify: int, quantize: int
)


@router.get("/area/by-parent/{area_id}.geojson", response=schemas.FeatureCollection)
@router.get("/area/by-parent/{area_id}.geojson", response=FeatureCollection)
def area_children(request, area_id: int):
"""
Returns the direct descendants of a given Area as a FeatureCollection
Expand All @@ -55,7 +57,7 @@ def area_children(request, area_id: int):
return models.Area.features.filter(parent=area_id).to_featurecollection()


@router.get("/area/by-type/{area_type}-s{simplify}-q{quantize}.geojson", response=schemas.FeatureCollection)
@router.get("/area/by-type/{area_type}-s{simplify}-q{quantize}.geojson", response=FeatureCollection)
def area_type_compressed(request, area_type: str, simplify: int, quantize: int):
"""
Returns all areas of a given type
Expand All @@ -66,7 +68,7 @@ def area_type_compressed(request, area_type: str, simplify: int, quantize: int):
)


@router.get("/area/by-type/{area_type}.geojson", response=schemas.FeatureCollection)
@router.get("/area/by-type/{area_type}.geojson", response=FeatureCollection)
def area_type(request, area_type: str):
"""
Returns all areas of a given type
Expand Down
42 changes: 0 additions & 42 deletions simple_locations/schemas.py

This file was deleted.

2 changes: 1 addition & 1 deletion tests/test_feature_manager.py
Original file line number Diff line number Diff line change
Expand Up @@ -5,7 +5,7 @@

from simple_locations.gis_functions import AsGeoJson, JsonFeature
from simple_locations.models import Area
from simple_locations.schemas import Feature, FeatureCollection
from geojson_pydantic import FeatureCollection, Feature
from tests.factories import AreaFactory # type: ignore


Expand Down
2 changes: 1 addition & 1 deletion tests/test_settings.py
Original file line number Diff line number Diff line change
Expand Up @@ -80,7 +80,7 @@


# Temporary:
# docker run --rm -p 49155:5432 --name=djangostreetmap -e POSTGRES_PASSWORD=post1234 postgis/postgis:14-3.2 -c fsync=off -c shared_buffers=4096MB
# docker run --rm -p 49156:5432 --name=dird -e POSTGRES_PASSWORD=dird -e POSTGRES_DB=dird_db -e POSTGRES_USER=dird postgis/postgis:14-3.2 -c fsync=off -c shared_buffers=4096MB
DATABASES = {
"default": {
"ENGINE": "django.contrib.gis.db.backends.postgis",
Expand Down

0 comments on commit 45d0363

Please sign in to comment.