From 5278ad39d073585a1bc29cd1179a0eaf9d13fe77 Mon Sep 17 00:00:00 2001
From: pacnpal <183241239+pacnpal@users.noreply.github.com>
Date: Fri, 21 Feb 2025 20:37:03 -0500
Subject: [PATCH] Refactor imports and improve code organization: streamline
import statements and enhance readability in parks/views.py
---
parks/views.py | 101 +++++++++++++++++++++++++++----------------------
1 file changed, 55 insertions(+), 46 deletions(-)
diff --git a/parks/views.py b/parks/views.py
index c0c686fa..a0c4e148 100644
--- a/parks/views.py
+++ b/parks/views.py
@@ -1,3 +1,24 @@
+from .querysets import get_base_park_queryset
+from search.mixins import HTMXFilterableMixin
+from reviews.models import Review
+from location.models import Location
+from media.models import Photo
+from moderation.models import EditSubmission
+from moderation.mixins import EditSubmissionMixin, PhotoSubmissionMixin, HistoryMixin
+from core.views import SlugRedirectMixin
+from .filters import ParkFilter
+from .forms import ParkForm
+from .models import Park, ParkArea
+from django.http import HttpResponseRedirect, HttpResponse, HttpRequest, JsonResponse
+from django.core.exceptions import ObjectDoesNotExist
+from django.contrib import messages
+from django.contrib.contenttypes.models import ContentType
+from django.contrib.auth.mixins import LoginRequiredMixin
+from django.db.models import Q, Count, QuerySet
+from django.urls import reverse
+from django.shortcuts import get_object_or_404, render
+from decimal import InvalidOperation
+from django.views.generic import DetailView, ListView, CreateView, UpdateView
import requests
from decimal import Decimal, ROUND_DOWN
from typing import Any, Optional, cast, Literal
@@ -8,26 +29,6 @@ PARK_LIST_ITEM_TEMPLATE = "parks/partials/park_list_item.html"
REQUIRED_FIELDS_ERROR = "Please correct the errors below. Required fields are marked with an asterisk (*)."
ALLOWED_ROLES = ["MODERATOR", "ADMIN", "SUPERUSER"]
-from django.views.generic import DetailView, ListView, CreateView, UpdateView
-from decimal import InvalidOperation
-from django.shortcuts import get_object_or_404, render
-from django.urls import reverse
-from django.db.models import Q, Count, QuerySet
-from django.contrib.auth.mixins import LoginRequiredMixin
-from django.contrib.contenttypes.models import ContentType
-from django.contrib import messages
-from django.core.exceptions import ObjectDoesNotExist
-from django.http import HttpResponseRedirect, HttpResponse, HttpRequest, JsonResponse
-from .models import Park, ParkArea
-from .forms import ParkForm
-from .filters import ParkFilter
-from core.views import SlugRedirectMixin
-from moderation.mixins import EditSubmissionMixin, PhotoSubmissionMixin, HistoryMixin
-from moderation.models import EditSubmission
-from media.models import Photo
-from location.models import Location
-from reviews.models import Review
-from search.mixins import HTMXFilterableMixin
ViewMode = Literal["grid", "list"]
@@ -35,19 +36,19 @@ ViewMode = Literal["grid", "list"]
def normalize_osm_result(result: dict) -> dict:
"""Normalize OpenStreetMap result to a consistent format with enhanced address details"""
from .location_utils import get_english_name, normalize_coordinate
-
+
# Get address details
address = result.get('address', {})
-
+
# Normalize coordinates
lat = normalize_coordinate(float(result.get('lat')), 9, 6)
lon = normalize_coordinate(float(result.get('lon')), 10, 6)
-
+
# Get English names where possible
name = ''
if 'namedetails' in result:
name = get_english_name(result['namedetails'])
-
+
# Build street address from available components
street_parts = []
if address.get('house_number'):
@@ -58,30 +59,30 @@ def normalize_osm_result(result: dict) -> dict:
street_parts.append(address['pedestrian'])
elif address.get('footway'):
street_parts.append(address['footway'])
-
+
# Handle additional address components
suburb = address.get('suburb', '')
district = address.get('district', '')
neighborhood = address.get('neighbourhood', '')
-
+
# Build city from available components
city = (address.get('city') or
address.get('town') or
address.get('village') or
address.get('municipality') or
'')
-
+
# Get detailed state/region information
state = (address.get('state') or
address.get('province') or
address.get('region') or
'')
-
+
# Get postal code with fallbacks
postal_code = (address.get('postcode') or
- address.get('postal_code') or
- '')
-
+ address.get('postal_code') or
+ '')
+
return {
'display_name': name or result.get('display_name', ''),
'lat': lat,
@@ -96,29 +97,30 @@ def normalize_osm_result(result: dict) -> dict:
'postal_code': postal_code,
}
+
def get_view_mode(request: HttpRequest) -> ViewMode:
"""Get the current view mode from request, defaulting to grid"""
view_mode = request.GET.get('view_mode', 'grid')
return cast(ViewMode, 'list' if view_mode == 'list' else 'grid')
-from .querysets import get_base_park_queryset
-
def add_park_button(request: HttpRequest) -> HttpResponse:
"""Return the add park button partial template"""
return render(request, "parks/partials/add_park_button.html")
+
def park_actions(request: HttpRequest, slug: str) -> HttpResponse:
"""Return the park actions partial template"""
park = get_object_or_404(Park, slug=slug)
return render(request, "parks/partials/park_actions.html", {"park": park})
+
def get_park_areas(request: HttpRequest) -> HttpResponse:
"""Return park areas as options for a select element"""
park_id = request.GET.get('park')
if not park_id:
return HttpResponse('')
-
+
try:
park = Park.objects.get(id=park_id)
areas = park.areas.all()
@@ -131,6 +133,7 @@ def get_park_areas(request: HttpRequest) -> HttpResponse:
except Park.DoesNotExist:
return HttpResponse('')
+
def location_search(request: HttpRequest) -> JsonResponse:
"""Search for locations using OpenStreetMap Nominatim API"""
query = request.GET.get("q", "")
@@ -153,7 +156,8 @@ def location_search(request: HttpRequest) -> JsonResponse:
if response.status_code == 200:
results = response.json()
- normalized_results = [normalize_osm_result(result) for result in results]
+ normalized_results = [normalize_osm_result(
+ result) for result in results]
valid_results = [
r for r in normalized_results
if r["lat"] is not None and r["lon"] is not None
@@ -162,6 +166,7 @@ def location_search(request: HttpRequest) -> JsonResponse:
return JsonResponse({"results": []})
+
def reverse_geocode(request: HttpRequest) -> JsonResponse:
"""Reverse geocode coordinates using OpenStreetMap Nominatim API"""
try:
@@ -217,11 +222,11 @@ class ParkListView(HTMXFilterableMixin, ListView):
if self.request.htmx:
return ["parks/partials/park_list_item.html"]
return [self.template_name]
-
+
def get_view_mode(self) -> ViewMode:
"""Get the current view mode (grid or list)"""
return get_view_mode(self.request)
-
+
def get_queryset(self) -> QuerySet[Park]:
"""Get base queryset with annotations and apply filters"""
try:
@@ -229,7 +234,7 @@ class ParkListView(HTMXFilterableMixin, ListView):
except Exception as e:
messages.error(self.request, f"Error loading parks: {str(e)}")
queryset = self.model.objects.none()
-
+
# Always initialize filterset, even if queryset failed
self.filterset = self.get_filter_class()(self.request.GET, queryset=queryset)
return self.filterset.qs
@@ -243,7 +248,7 @@ class ParkListView(HTMXFilterableMixin, ListView):
self.request.GET,
queryset=self.model.objects.none()
)
-
+
context = super().get_context_data(**kwargs)
context.update({
'view_mode': self.get_view_mode(),
@@ -311,6 +316,7 @@ def search_parks(request: HttpRequest) -> HttpResponse:
response['HX-Trigger'] = 'searchError'
return response
+
class ParkCreateView(LoginRequiredMixin, CreateView):
model = Park
form_class = ParkForm
@@ -324,7 +330,8 @@ class ParkCreateView(LoginRequiredMixin, CreateView):
data["opening_date"] = data["opening_date"].isoformat()
if data.get("closing_date"):
data["closing_date"] = data["closing_date"].isoformat()
- decimal_fields = ["latitude", "longitude", "size_acres", "average_rating"]
+ decimal_fields = ["latitude", "longitude",
+ "size_acres", "average_rating"]
for field in decimal_fields:
if data.get(field):
data[field] = str(data[field])
@@ -375,7 +382,8 @@ class ParkCreateView(LoginRequiredMixin, CreateView):
location_type="park",
latitude=form.cleaned_data["latitude"],
longitude=form.cleaned_data["longitude"],
- street_address=form.cleaned_data.get("street_address", ""),
+ street_address=form.cleaned_data.get(
+ "street_address", ""),
city=form.cleaned_data.get("city", ""),
state=form.cleaned_data.get("state", ""),
country=form.cleaned_data.get("country", ""),
@@ -389,7 +397,8 @@ class ParkCreateView(LoginRequiredMixin, CreateView):
Photo.objects.create(
image=photo_file,
uploaded_by=self.request.user,
- content_type=ContentType.objects.get_for_model(Park),
+ content_type=ContentType.objects.get_for_model(
+ Park),
object_id=self.object.id,
)
uploaded_count += 1
@@ -444,7 +453,8 @@ class ParkUpdateView(LoginRequiredMixin, UpdateView):
data["opening_date"] = data["opening_date"].isoformat()
if data.get("closing_date"):
data["closing_date"] = data["closing_date"].isoformat()
- decimal_fields = ["latitude", "longitude", "size_acres", "average_rating"]
+ decimal_fields = ["latitude", "longitude",
+ "size_acres", "average_rating"]
for field in decimal_fields:
if data.get(field):
data[field] = str(data[field])
@@ -516,7 +526,8 @@ class ParkUpdateView(LoginRequiredMixin, UpdateView):
Photo.objects.create(
image=photo_file,
uploaded_by=self.request.user,
- content_type=ContentType.objects.get_for_model(Park),
+ content_type=ContentType.objects.get_for_model(
+ Park),
object_id=self.object.id,
)
uploaded_count += 1
@@ -651,5 +662,3 @@ class ParkAreaDetailView(
def get_redirect_url_kwargs(self) -> dict[str, str]:
area = cast(ParkArea, self.object)
return {"park_slug": area.park.slug, "area_slug": area.slug}
-
-