Skip to content

Commit

Permalink
Gs filter on municipality (#26)
Browse files Browse the repository at this point in the history
municipalities loading vue + overwriting save() method on observations and making municipality a computed field here
  • Loading branch information
stevegerrits authored Mar 21, 2024
1 parent 3cb3f72 commit b624d42
Show file tree
Hide file tree
Showing 19 changed files with 333 additions and 131 deletions.
11 changes: 10 additions & 1 deletion docker-compose.yml
Original file line number Diff line number Diff line change
Expand Up @@ -11,7 +11,6 @@ services:
tty: true
volumes:
- .:/workspaces/vespadb/

app:
build:
context: .
Expand All @@ -37,6 +36,16 @@ services:
volumes:
- postgres_data:/var/lib/postgresql/data

pgadmin:
image: dpage/pgadmin4
environment:
PGADMIN_DEFAULT_EMAIL: "[email protected]"
PGADMIN_DEFAULT_PASSWORD: "root"
ports:
- "5050:80"
depends_on:
- db

volumes:
postgres_data:

Expand Down
109 changes: 70 additions & 39 deletions frontend/src/components/FilterComponent.vue
Original file line number Diff line number Diff line change
@@ -1,63 +1,94 @@
<template>
<v-row>
<v-col cols="5" sm="3" md="3" lg="3"class="d-flex align-start">
<v-autocomplete
v-model="selectedGemeentes"
:menu-props="{ maxHeight: 500 }"
:items="gemeentes"
label="Selecteer gemeente(s)"
multiple
chips
dense
solo
></v-autocomplete>
</v-col>

<v-col cols="5" sm="3" md="3" lg="3"class="d-flex align-start">
<v-autocomplete
v-model="selectedJaartallen"
:items="jaartallen"
label="Selecteer jaartal(len)"
multiple
chips
dense
solo
></v-autocomplete>
</v-col>

<v-col cols="2" sm="3" md="3" lg="3" class="d-flex align-start">
<v-switch
v-model="anbAreasActief"
:label="`ANB Areas ${anbAreasActief ? 'Aan' : 'Uit'}`"
:color="anbAreasActief ? '#4C7742' : ''"
></v-switch>
</v-col>
</v-row>
<v-row>
<v-col v-if="formattedMunicipalities.length > 0" cols="5" sm="3" md="3" lg="3" class="d-flex align-start">
<v-autocomplete
v-model="selectedMunicipalities"
:items="municipalities.length ? municipalities.map(municipality => ({
title: municipality.name,
value: municipality.id
})) : []"
item-text="title"
item-value="value"
label="Selecteer gemeente(s)"
multiple
chips
dense
solo
@change="emitFilterUpdate">
</v-autocomplete>
</v-col>
<v-col cols="5" sm="3" md="3" lg="3" class="d-flex align-start">
<v-autocomplete
v-model="selectedYears"
:items="jaartallen"
label="Selecteer jaartal(len)"
multiple
chips
dense
solo
@change="emitFilterUpdate"
></v-autocomplete>
</v-col>
<v-col cols="2" sm="3" md="3" lg="3" class="d-flex align-start">
<v-switch
v-model="anbAreasActief"
:label="`ANB Areas ${anbAreasActief ? 'Aan' : 'Uit'}`"
:color="anbAreasActief ? '#4C7742' : ''"
@change="emitFilterUpdate"
></v-switch>
</v-col>
</v-row>
</template>

<script>
import ApiService from '@/services/apiService';
export default {
data: () => ({
selectedGemeentes: [],
gemeentes: [],
selectedJaartallen: [],
selectedMunicipalities: [],
municipalities: [],
selectedYears: [],
jaartallen: [2020, 2021, 2022, 2023],
anbAreasActief: false,
smallScreen: false,
}),
computed: {
formattedMunicipalities() {
const formatted_municipalities = this.municipalities.map(municipality => {
console.log('Formatted municipality:', municipality);
return {
name: municipality.name,
id: municipality.id
};
});
console.log('formattedMunicipalities:', formatted_municipalities);
return formatted_municipalities;
},
},
methods: {
async fetchMunicipalities() {
try {
const response = await ApiService.get('/municipalities/');
if (response.status === 200) {
this.gemeentes = response.data.map(municipality => municipality.name);
console.log('Fetched municipalities (raw):', response.data);
this.municipalities = response.data;
const formatted_municipalities = this.municipalities.map(municipality => ({
name: municipality.name,
id: municipality.id
}));
this.formattedMunicipalities = formatted_municipalities;
} else {
console.error('Failed to fetch municipalities: Status Code', response.status);
}
} catch (error) {
console.error('Error fetching municipalities:', error);
}
},
emitFilterUpdate() {
this.$emit('updateFilters', {
selectedMunicipalities: this.selectedMunicipalities,
selectedYears: this.selectedYears,
anbAreasActief: this.anbAreasActief
});
},
},
created() {
this.fetchMunicipalities();
Expand Down
42 changes: 37 additions & 5 deletions poetry.lock

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

1 change: 1 addition & 0 deletions pyproject.toml
Original file line number Diff line number Diff line change
Expand Up @@ -30,6 +30,7 @@ django-cors-headers = "^4.3.1"
djangorestframework-jwt = "^1.11.0"
djangorestframework-simplejwt = "^5.3.1"
geopandas = "^0.14.3"
factory-boy = "^3.2.0"

[tool.poetry.group.dev.dependencies] # https://python-poetry.org/docs/master/managing-dependencies/
coverage = { extras = ["toml"], version = ">=7.4.1" }
Expand Down
2 changes: 1 addition & 1 deletion tests/__init__.py
Original file line number Diff line number Diff line change
@@ -1 +1 @@
"""Test vespadb."""
"""."""
2 changes: 1 addition & 1 deletion tests/conftest.py
Original file line number Diff line number Diff line change
@@ -1 +1 @@
"""Pytest configuration."""
"""."""
2 changes: 1 addition & 1 deletion tests/vespadb/__init__.py
Original file line number Diff line number Diff line change
@@ -1 +1 @@
"""Test vespadb."""
"""."""
1 change: 1 addition & 0 deletions vespadb/management/commands/data/Refgem.prj
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
PROJCS["Belge_Lambert_1972",GEOGCS["GCS_Belge_1972",DATUM["D_Belge_1972",SPHEROID["International_1924",6378388.0,297.0]],PRIMEM["Greenwich",0.0],UNIT["Degree",0.0174532925199433]],PROJECTION["Lambert_Conformal_Conic"],PARAMETER["False_Easting",150000.01256],PARAMETER["False_Northing",5400088.4378],PARAMETER["Central_Meridian",4.367486666666666],PARAMETER["Standard_Parallel_1",49.8333339],PARAMETER["Standard_Parallel_2",51.16666723333333],PARAMETER["Latitude_Of_Origin",90.0],UNIT["Meter",1.0]]
67 changes: 29 additions & 38 deletions vespadb/management/commands/load_municipalities.py
Original file line number Diff line number Diff line change
@@ -1,53 +1,44 @@
"""Handle the load_municipalities command."""
"""Handlers."""

from pathlib import Path
from typing import Any

import geopandas as gpd
from django.contrib.gis.geos import GEOSGeometry, MultiPolygon, Polygon
from django.contrib.gis.utils import LayerMapping
from django.core.management.base import BaseCommand

from vespadb.observations.models import Municipality

# A mapping dictionary to map field names from the Shapefile to the Municipality model fields.
municipality_mapping = {
"oidn": "OIDN",
"uidn": "UIDN",
"terrid": "TERRID",
"nis_code": "NISCODE",
"name": "NAAM",
"datpublbs": "DATPUBLBS",
"numac": "NUMAC",
"length": "LENGTE",
"surface": "OPPERVL",
"polygon": "MULTIPOLYGON",
}


class Command(BaseCommand):
"""Load municipalities from a Shapefile into the database."""
"""A custom management command that loads a ShapeFile containing municipality boundaries into the database.
help = "Load municipalities from a Shapefile into the database"
This command uses the LayerMapping utility from Django's GIS framework to perform the data import.
"""

def handle(self, *args: Any, **kwargs: Any) -> None:
"""
Load the municipalities from the Shapefile into the database.
help: str = "Laadt een ShapeFile met gemeentegrenzen in de database."

Args:
*args (Any): Variable length argument list.
**kwargs (Any): Arbitrary keyword arguments.
def handle(self, *args: Any, **options: Any) -> None:
"""
Handle municipality data loading.
Returns
-------
None
:param args: Variable length argument list.
:param options: Arbitrary keyword arguments.
"""
# Load the GeoDataFrame from the Shapefile
script_dir = Path(__file__).parent
shp_path = script_dir / "data/Refgem.shp"

gdf = gpd.read_file(str(shp_path))
for _, row in gdf.iterrows():
nis_code = row["NISCODE"]
name = row["NAAM"]
geometry = GEOSGeometry(row["geometry"].wkt)

if isinstance(geometry, Polygon):
geometry = MultiPolygon(geometry)

municipality, created = Municipality.objects.get_or_create(
name=name, nis_code=nis_code, defaults={"polygon": geometry}
)

if created:
self.stdout.write(self.style.SUCCESS(f'Municipality "{name}" successfully saved.'))
else:
# Update the polygon geometry if the municipality exists
municipality.polygon = geometry
municipality.save()
self.stdout.write(self.style.SUCCESS(f'Municipality "{name}" updated.'))
shapefile_path: str = str((Path(__file__).parent / "data" / "Refgem.shp").resolve())

lm = LayerMapping(Municipality, shapefile_path, municipality_mapping, transform=False, encoding="iso-8859-1")
lm.save(strict=True, verbose=True)
2 changes: 0 additions & 2 deletions vespadb/observations/__init__.py
Original file line number Diff line number Diff line change
@@ -1,3 +1 @@
"""."""

default_app_config = "vespadb.observations.apps.ObservationsConfig"
12 changes: 11 additions & 1 deletion vespadb/observations/migrations/0001_initial.py
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
# Generated by Django 5.0.3 on 2024-03-19 12:05
# Generated by Django 5.0.3 on 2024-03-21 17:30

import django.contrib.gis.db.models.fields
import django.db.models.deletion
Expand All @@ -15,6 +15,15 @@ class Migration(migrations.Migration):
]

operations = [
migrations.CreateModel(
name='Municipality',
fields=[
('id', models.AutoField(primary_key=True, serialize=False)),
('name', models.CharField(max_length=255)),
('nis_code', models.CharField(max_length=255)),
('polygon', django.contrib.gis.db.models.fields.PolygonField(srid=4326)),
],
),
migrations.CreateModel(
name='Observation',
fields=[
Expand Down Expand Up @@ -49,6 +58,7 @@ class Migration(migrations.Migration):
('images', models.JSONField(default=list)),
('created_by', models.ForeignKey(null=True, on_delete=django.db.models.deletion.SET_NULL, related_name='created_observations', to=settings.AUTH_USER_MODEL)),
('modified_by', models.ForeignKey(null=True, on_delete=django.db.models.deletion.SET_NULL, related_name='modified_observations', to=settings.AUTH_USER_MODEL)),
('municipality', models.ForeignKey(blank=True, null=True, on_delete=django.db.models.deletion.SET_NULL, related_name='observations', to='observations.municipality')),
],
),
]
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
# Generated by Django 5.0.3 on 2024-03-20 09:46
# Generated by Django 5.0.3 on 2024-03-21 18:43

import django.contrib.gis.db.models.fields
from django.db import migrations
Expand All @@ -7,7 +7,7 @@
class Migration(migrations.Migration):

dependencies = [
('observations', '0002_municipality'),
('observations', '0001_initial'),
]

operations = [
Expand Down
23 changes: 0 additions & 23 deletions vespadb/observations/migrations/0002_municipality.py

This file was deleted.

Loading

0 comments on commit b624d42

Please sign in to comment.