From be97ac32fbbb236192fd9949147cf3a51836e63c Mon Sep 17 00:00:00 2001 From: moanos Date: Thu, 26 Dec 2024 16:55:37 +0100 Subject: [PATCH] refactor: Move search into class --- src/fellchensammlung/forms.py | 2 +- src/fellchensammlung/tools/search.py | 58 ++++++++++++++++++++++++++++ src/fellchensammlung/views.py | 40 ++++++------------- 3 files changed, 70 insertions(+), 30 deletions(-) create mode 100644 src/fellchensammlung/tools/search.py diff --git a/src/fellchensammlung/forms.py b/src/fellchensammlung/forms.py index 78e956d..2b409ca 100644 --- a/src/fellchensammlung/forms.py +++ b/src/fellchensammlung/forms.py @@ -182,7 +182,7 @@ class CustomRegistrationForm(RegistrationForm): class AdoptionNoticeSearchForm(forms.Form): - location = forms.CharField(max_length=20, label=_("Stadt"), required=False) + location_string = forms.CharField(max_length=20, label=_("Stadt"), required=False) max_distance = forms.ChoiceField(choices=DistanceChoices, initial=DistanceChoices.ONE_HUNDRED, label=_("Suchradius")) sex = forms.ChoiceField(choices=SexChoicesWithAll, label=_("Geschlecht"), required=False, initial=SexChoicesWithAll.ALL) diff --git a/src/fellchensammlung/tools/search.py b/src/fellchensammlung/tools/search.py new file mode 100644 index 0000000..bce87fa --- /dev/null +++ b/src/fellchensammlung/tools/search.py @@ -0,0 +1,58 @@ +import logging + +from .geo import GeoAPI +from ..forms import AdoptionNoticeSearchForm +from ..models import SearchSubscription, AdoptionNotice, BaseNotification, SexChoicesWithAll, Location + + +def notify_search_subscribers(new_adoption_notice: AdoptionNotice): + for search_subscription in SearchSubscription.objects.all(): + BaseNotification.objects.create(user=search_subscription.owner) + + +class Search(): + def __init__(self): + self.sex = None + self.area_search = None + self.max_distance = None + self.location_string = None + self.search_position = None + self.location = None + self.place_not_found = False # Indicates that a location was given but could not be geocoded + self.search_form = None + + def get_adoption_notices(self): + adoptions = AdoptionNotice.objects.order_by("-created_at") + adoptions = [adoption for adoption in adoptions if adoption.is_active] + if self.sex is not None and self.sex != SexChoicesWithAll.ALL: + adoptions = [adoption for adoption in adoptions if self.sex in adoption.sexes] + if self.area_search and not self.place_not_found: + adoptions = [a for a in adoptions if a.in_distance(self.search_position, self.max_distance)] + + return adoptions + + def search_from_request(self, request): + if request.method == 'POST': + self.search_form = AdoptionNoticeSearchForm(request.POST) + self.search_form.is_valid() + self.sex = self.search_form.cleaned_data["sex"] + if self.search_form.cleaned_data["location_string"] != "" and self.search_form.cleaned_data["max_distance"] != "": + self.area_search = True + self.location_string = self.search_form.cleaned_data["location_string"] + self.max_distance = int(self.search_form.cleaned_data["max_distance"]) + + geo_api = GeoAPI() + self.search_position = geo_api.get_coordinates_from_query(self.location_string) + if self.search_position is None: + self.place_not_found = True + else: + self.search_form = AdoptionNoticeSearchForm() + + def subscribe(self, user): + logging.info(f"{user} subscribed to search") + + location = Location.get_location_from_string(self.location_string) + SearchSubscription.objects.create(owner=user, + location=location, + sex=self.sex, + radius=self.max_distance) diff --git a/src/fellchensammlung/views.py b/src/fellchensammlung/views.py index f088112..b210d83 100644 --- a/src/fellchensammlung/views.py +++ b/src/fellchensammlung/views.py @@ -28,6 +28,8 @@ from .tools.admin import clean_locations, get_unchecked_adoption_notices, deacti from .tasks import add_adoption_notice_location from rest_framework.authtoken.models import Token +from .tools.search import Search + def user_is_trust_level_or_above(user, trust_level=TrustLevel.MODERATOR): return user.is_authenticated and user.trust_level >= trust_level @@ -169,37 +171,17 @@ def animal_detail(request, animal_id): def search(request): - latest_adoption_list = AdoptionNotice.objects.order_by("-created_at") - active_adoptions = [adoption for adoption in latest_adoption_list if adoption.is_active] + search = Search() + search.search_from_request(request) if request.method == 'POST': + if "subscribe_to_search" in request.POST: + # Make sure user is logged in + if not request.user.is_authenticated: + return redirect(f"{settings.LOGIN_URL}?next={request.path}") - sex = request.POST.get("sex") - if sex != SexChoicesWithAll.ALL: - active_adoptions = [adoption for adoption in active_adoptions if sex in adoption.sexes] - - search_form = AdoptionNoticeSearchForm(request.POST) - search_form.is_valid() - if search_form.cleaned_data["location"] == "": - adoption_notices_in_distance = active_adoptions - place_not_found = False - else: - max_distance = int(request.POST.get('max_distance')) - if max_distance == "": - max_distance = None - geo_api = GeoAPI() - search_position = geo_api.get_coordinates_from_query(request.POST['location']) - if search_position is None: - place_not_found = True - adoption_notices_in_distance = active_adoptions - else: - place_not_found = False - adoption_notices_in_distance = [a for a in active_adoptions if a.in_distance(search_position, max_distance)] - - context = {"adoption_notices": adoption_notices_in_distance, "search_form": search_form, - "place_not_found": place_not_found} - else: - search_form = AdoptionNoticeSearchForm() - context = {"adoption_notices": active_adoptions, "search_form": search_form} + search.subscribe(request.user) + context = {"adoption_notices": search.get_adoption_notices(), "search_form": search.search_form, + "place_not_found": search.place_not_found} return render(request, 'fellchensammlung/search.html', context=context)