diff --git a/src/fellchensammlung/management/commands/clean_locations.py b/src/fellchensammlung/management/commands/clean_locations.py index 21d9546..e551aa7 100644 --- a/src/fellchensammlung/management/commands/clean_locations.py +++ b/src/fellchensammlung/management/commands/clean_locations.py @@ -1,5 +1,6 @@ from django.core.management import BaseCommand from fellchensammlung.models import AdoptionNotice, Location +from fellchensammlung.tools.geo import clean_locations class Command(BaseCommand): @@ -14,19 +15,4 @@ class Command(BaseCommand): ) def handle(self, *args, **options): - adoption_notices_without_location = AdoptionNotice.objects.filter(location__isnull=True) - num_of_all = AdoptionNotice.objects.count() - num_without_location = adoption_notices_without_location.count() - print(f"From {num_of_all} there are {num_without_location} adoption notices without location " - f"({num_without_location/num_of_all*100:.2f}%)") - for adoption_notice in adoption_notices_without_location: - print(f"Searching {adoption_notice.location_string} in Nominatim") - location = Location.get_location_from_string(adoption_notice.location_string) - if location: - adoption_notice.location = location - adoption_notice.save() - - adoption_notices_without_location_new = AdoptionNotice.objects.filter(location__isnull=True) - num_without_location_new = adoption_notices_without_location_new.count() - num_new = num_without_location - num_without_location_new - print(f"Added {num_new} new locations") + clean_locations(quiet=False) \ No newline at end of file diff --git a/src/fellchensammlung/templates/fellchensammlung/instance-health-check.html b/src/fellchensammlung/templates/fellchensammlung/instance-health-check.html new file mode 100644 index 0000000..15a8612 --- /dev/null +++ b/src/fellchensammlung/templates/fellchensammlung/instance-health-check.html @@ -0,0 +1,15 @@ +{% extends "fellchensammlung/base_generic.html" %} +{% load i18n %} + +{% block content %} +
+

{% translate "Instanz-Check" %}

+

{% translate "Nicht-lokalisierte Vermittlungen" %}: {{ number_not_geocoded_adoption_notices }}/{{ number_of_adoption_notices }}

+

{% translate "Nicht-lokalisierte Tierschutzorganisationen" %}: {{ number_not_geocoded_rescue_orgs }}/{{ number_of_rescue_orgs }}

+
+
+ {% csrf_token %} + + +
+{% endblock %} diff --git a/src/fellchensammlung/tools/admin.py b/src/fellchensammlung/tools/admin.py new file mode 100644 index 0000000..774097d --- /dev/null +++ b/src/fellchensammlung/tools/admin.py @@ -0,0 +1,44 @@ +from fellchensammlung.models import AdoptionNotice, Location, RescueOrganization + +def clean_locations(quiet=True): + # ADOPTION NOTICES + adoption_notices_without_location = AdoptionNotice.objects.filter(location__isnull=True) + num_of_all = AdoptionNotice.objects.count() + num_without_location = adoption_notices_without_location.count() + if not quiet: + print(f"From {num_of_all} there are {num_without_location} adoption notices without location " + f"({num_without_location/num_of_all*100:.2f}%)") + for adoption_notice in adoption_notices_without_location: + if not quiet: + print(f"Searching {adoption_notice.location_string} in Nominatim") + location = Location.get_location_from_string(adoption_notice.location_string) + if location: + adoption_notice.location = location + adoption_notice.save() + + adoption_notices_without_location_new = AdoptionNotice.objects.filter(location__isnull=True) + num_without_location_new = adoption_notices_without_location_new.count() + num_new = num_without_location - num_without_location_new + if not quiet: + print(f"Added {num_new} new locations") + + # RESCUE ORGANIZATIONS + rescue_orgs_without_location = RescueOrganization.objects.filter(location__isnull=True) + num_of_all = RescueOrganization.objects.count() + num_without_location = rescue_orgs_without_location.count() + if not quiet: + print(f"From {num_of_all} there are {num_without_location} adoption notices without location " + f"({num_without_location/num_of_all*100:.2f}%)") + for rescue_org in rescue_orgs_without_location: + if not quiet: + print(f"Searching {rescue_org.location_string} in Nominatim") + location = Location.get_location_from_string(rescue_org.location_string) + if location: + rescue_org.location = location + rescue_org.save() + + rescue_orgs_without_location_new = RescueOrganization.objects.filter(location__isnull=True) + num_without_location_new = rescue_orgs_without_location_new.count() + num_new = num_without_location - num_without_location_new + if not quiet: + print(f"Added {num_new} new locations") \ No newline at end of file diff --git a/src/fellchensammlung/tools/geo.py b/src/fellchensammlung/tools/geo.py index e1297a7..ceacbfc 100644 --- a/src/fellchensammlung/tools/geo.py +++ b/src/fellchensammlung/tools/geo.py @@ -1,11 +1,11 @@ import logging - import requests import json +from math import radians, sqrt, sin, cos, atan2 + from notfellchen import __version__ as nf_version from notfellchen import settings -from math import radians, sqrt, sin, cos, atan2 def calculate_distance_between_coordinates(position1, position2): diff --git a/src/fellchensammlung/urls.py b/src/fellchensammlung/urls.py index b349854..64fc74e 100644 --- a/src/fellchensammlung/urls.py +++ b/src/fellchensammlung/urls.py @@ -59,6 +59,11 @@ urlpatterns = [ path('accounts/', include('django_registration.backends.activation.urls')), path('accounts/', include('django.contrib.auth.urls')), - path('change-language', views.change_language, name="change-language") + path('change-language', views.change_language, name="change-language"), + + ########### + ## ADMIN ## + ########### + path('instance-health-check', views.instance_health_check, name="instance-health-check") ] diff --git a/src/fellchensammlung/views.py b/src/fellchensammlung/views.py index 77f7bfc..a013623 100644 --- a/src/fellchensammlung/views.py +++ b/src/fellchensammlung/views.py @@ -6,20 +6,21 @@ from django.urls import reverse from django.contrib.auth.decorators import login_required from django.utils import translation from django.core.exceptions import PermissionDenied +from django.contrib.auth.decorators import user_passes_test from .mail import mail_admins_new_report from notfellchen import settings from fellchensammlung import logger from .models import AdoptionNotice, Text, Animal, Rule, Image, Report, ModerationAction, \ - User, Location, AdoptionNoticeStatus, Subscriptions, CommentNotification, BaseNotification + User, Location, AdoptionNoticeStatus, Subscriptions, CommentNotification, BaseNotification, RescueOrganization from .forms import AdoptionNoticeForm, AdoptionNoticeFormWithDateWidget, ImageForm, ReportAdoptionNoticeForm, \ CommentForm, ReportCommentForm, AnimalForm, \ AdoptionNoticeSearchForm, AnimalFormWithDateWidget from .models import Language, Announcement from .tools.geo import GeoAPI from .tools.metrics import gather_metrics_data -from django.contrib.auth.decorators import user_passes_test +from .tools.admin import clean_locations def user_is_trust_level_or_above(user, trust_level=User.MODERATOR): @@ -411,3 +412,28 @@ def map(request): def metrics(request): data = gather_metrics_data() return JsonResponse(data) + +@login_required +def instance_health_check(request): + """ + Allows an administrator to check common problems of an instance + """ + if request.method == "POST": + action = request.POST.get("action") + if action == "clean_locations": + clean_locations(quiet=False) + + number_of_adoption_notices = AdoptionNotice.objects.all().count() + number_not_geocoded_adoption_notices = AdoptionNotice.objects.filter(location__isnull=True).count() + + number_of_rescue_orgs = RescueOrganization.objects.all().count() + number_not_geocoded_rescue_orgs = RescueOrganization.objects.filter(location__isnull=True).count() + context = { + "number_of_adoption_notices": number_of_adoption_notices, + "number_not_geocoded_adoption_notices": number_not_geocoded_adoption_notices, + "number_of_rescue_orgs": number_of_rescue_orgs, + "number_not_geocoded_rescue_orgs": number_not_geocoded_rescue_orgs + } + return render(request, 'fellchensammlung/instance-health-check.html', context=context) + +