diff --git a/pflaenzli/pflaenzli/admin.py b/pflaenzli/pflaenzli/admin.py index 1de3f16..f0ebb3f 100644 --- a/pflaenzli/pflaenzli/admin.py +++ b/pflaenzli/pflaenzli/admin.py @@ -1,5 +1,5 @@ from django.contrib import admin -from .models import Offer, Wish, PflaenzliUser +from .models import Offer, Wish, PflaenzliUser, Plz @admin.register(Offer) @@ -15,3 +15,8 @@ class WishAdmin(admin.ModelAdmin): @admin.register(PflaenzliUser) class UserAdmin(admin.ModelAdmin): list_display = ['id', 'username', 'email', 'zipcode', 'language_code', 'date_joined'] + + +@admin.register(Plz) +class PlzAdmin(admin.ModelAdmin): + list_display = ['id', 'name', 'plz', 'lat', 'lon'] diff --git a/pflaenzli/pflaenzli/management/commands/getplzindex.py b/pflaenzli/pflaenzli/management/commands/getplzindex.py index 0c0b99b..b3f000e 100644 --- a/pflaenzli/pflaenzli/management/commands/getplzindex.py +++ b/pflaenzli/pflaenzli/management/commands/getplzindex.py @@ -5,36 +5,52 @@ from urllib import request import pandas as pd from django.core.management.base import BaseCommand from pflaenzli_django.settings import BASE_DIR +from pflaenzli.models import Plz class Command(BaseCommand): help = 'Get the zip code index from post and compile it to a dataframe pickle' - def handle(self, *args, **options): - self.parse_data(self.download_geojson(api='v2', data='v2')) - self.stdout.write(self.style.SUCCESS('Done!')) + def add_arguments(self, parser): + parser.add_argument("--force", action="store_true", required=False) - def download_geojson(self, api, data): + def handle(self, *args, **options): + self.parse_data(*self.download_geojson(api='v2', data='v2', force=options["force"]), force=options["force"]) + + def download_geojson(self, api, data, force=False): file = f'plz_verzeichnis_{data}.json' - if os.path.exists(file): - self.stdout.write('File already downloaded. Skipping...\n') + if os.path.exists(file) and not force: + self.stdout.write('File already downloaded.') + self.stdout.write(self.style.SUCCESS( + 'Skipping...\n')) + exists = True else: self.stdout.write('Downloading geojson...') url = f'https://swisspost.opendatasoft.com/api/{api}/catalog/datasets/plz_verzeichnis_{data}/exports/geojson' request.urlretrieve(url, file) self.stdout.write(self.style.SUCCESS('Done!\n')) + exists = False - return file + return file, exists + + def parse_data(self, file, exists, force=False): + if exists and not force: + self.stdout.write(self.style.WARNING( + 'Nothing was done, if you want to redownload the PLZ index, use the --force option.\n')) + return - def parse_data(self, file): self.stdout.write('Opening file...') # Load the GeoJSON data for the zip codes with open(file, encoding='UTF-8') as f: full_data = json.load(f) self.stdout.write(self.style.SUCCESS('Done!\n')) - self.stdout.write('Parsing file...') - zip_dict = {} + self.stdout.write('Deleting existing data...') + Plz.objects.all().delete() + self.stdout.write(self.style.SUCCESS('Done!\n')) + + self.stdout.write('Parsing file and add new data...') + for plz_entry in full_data['features']: plz_entry = plz_entry['properties'] try: @@ -51,14 +67,12 @@ class Command(BaseCommand): if plz is None or lat is None or lon is None: continue - zip_dict[int(plz)] = [lat, lon] - self.stdout.write(self.style.SUCCESS('Done!\n')) + try: + name = plz_entry['ortbez27'] + except (KeyError, AttributeError, TypeError): + name = None - df = pd.DataFrame.from_dict(zip_dict, orient='index') - df.columns = ['lat', 'lon'] + plz, _ = Plz.objects.get_or_create(plz=int(plz), lat=lat, lon=lon, name=name) - self.stdout.write('Saving pickle...') - destination = os.path.join(BASE_DIR, 'pflaenzli', 'utils', 'plz.pkl') - df.to_pickle(destination) - - self.stdout.write(self.style.SUCCESS(f'Wrote pickle to {destination}\n')) + self.stdout.write(self.style.SUCCESS('Wrote PLZ data to the databse successfully\n')) + self.stdout.write(self.style.SUCCESS('Done!')) diff --git a/pflaenzli/pflaenzli/migrations/0006_plz.py b/pflaenzli/pflaenzli/migrations/0006_plz.py new file mode 100644 index 0000000..efbe8d2 --- /dev/null +++ b/pflaenzli/pflaenzli/migrations/0006_plz.py @@ -0,0 +1,31 @@ +# Generated by Django 4.2.5 on 2023-09-13 15:09 + +from django.db import migrations, models + + +class Migration(migrations.Migration): + + dependencies = [ + ("pflaenzli", "0005_pflaenzliuser_language_code_alter_offer_category"), + ] + + operations = [ + migrations.CreateModel( + name="Plz", + fields=[ + ( + "id", + models.BigAutoField( + auto_created=True, + primary_key=True, + serialize=False, + verbose_name="ID", + ), + ), + ("plz", models.IntegerField(verbose_name="PLZ")), + ("lat", models.DecimalField(decimal_places=6, max_digits=8)), + ("lon", models.DecimalField(decimal_places=6, max_digits=8)), + ("name", models.CharField(max_length=27)), + ], + ), + ] diff --git a/pflaenzli/pflaenzli/models.py b/pflaenzli/pflaenzli/models.py index b1e2b48..aa50a60 100644 --- a/pflaenzli/pflaenzli/models.py +++ b/pflaenzli/pflaenzli/models.py @@ -14,6 +14,13 @@ class PflaenzliUser(AbstractUser): language_code = models.CharField(max_length=2, default='de') +class Plz(models.Model): + plz = models.IntegerField(verbose_name='PLZ') + lat = models.DecimalField(max_digits=8, decimal_places=6) + lon = models.DecimalField(max_digits=8, decimal_places=6) + name = models.CharField(max_length=27) + + class Offer(models.Model): CATEGORIES = [ ('PLNT', _('Plant')), diff --git a/pflaenzli/pflaenzli/templates/base.html b/pflaenzli/pflaenzli/templates/base.html index 286d262..1e1f6a3 100644 --- a/pflaenzli/pflaenzli/templates/base.html +++ b/pflaenzli/pflaenzli/templates/base.html @@ -140,7 +140,7 @@
- {{ offer.zipcode }} + {% with plz=offer|get_plz %} {{ plz.plz }} {{ plz.name }}{% endwith %}
{% if dist %}@@ -90,7 +91,7 @@