mirror of
https://github.com/pacnpal/thrillwiki_django_no_react.git
synced 2025-12-20 07:11:08 -05:00
Refactor imports and improve code organization: streamline import statements and enhance readability in parks/views.py
This commit is contained in:
101
parks/views.py
101
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
|
import requests
|
||||||
from decimal import Decimal, ROUND_DOWN
|
from decimal import Decimal, ROUND_DOWN
|
||||||
from typing import Any, Optional, cast, Literal
|
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 (*)."
|
REQUIRED_FIELDS_ERROR = "Please correct the errors below. Required fields are marked with an asterisk (*)."
|
||||||
ALLOWED_ROLES = ["MODERATOR", "ADMIN", "SUPERUSER"]
|
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"]
|
ViewMode = Literal["grid", "list"]
|
||||||
|
|
||||||
@@ -35,19 +36,19 @@ ViewMode = Literal["grid", "list"]
|
|||||||
def normalize_osm_result(result: dict) -> dict:
|
def normalize_osm_result(result: dict) -> dict:
|
||||||
"""Normalize OpenStreetMap result to a consistent format with enhanced address details"""
|
"""Normalize OpenStreetMap result to a consistent format with enhanced address details"""
|
||||||
from .location_utils import get_english_name, normalize_coordinate
|
from .location_utils import get_english_name, normalize_coordinate
|
||||||
|
|
||||||
# Get address details
|
# Get address details
|
||||||
address = result.get('address', {})
|
address = result.get('address', {})
|
||||||
|
|
||||||
# Normalize coordinates
|
# Normalize coordinates
|
||||||
lat = normalize_coordinate(float(result.get('lat')), 9, 6)
|
lat = normalize_coordinate(float(result.get('lat')), 9, 6)
|
||||||
lon = normalize_coordinate(float(result.get('lon')), 10, 6)
|
lon = normalize_coordinate(float(result.get('lon')), 10, 6)
|
||||||
|
|
||||||
# Get English names where possible
|
# Get English names where possible
|
||||||
name = ''
|
name = ''
|
||||||
if 'namedetails' in result:
|
if 'namedetails' in result:
|
||||||
name = get_english_name(result['namedetails'])
|
name = get_english_name(result['namedetails'])
|
||||||
|
|
||||||
# Build street address from available components
|
# Build street address from available components
|
||||||
street_parts = []
|
street_parts = []
|
||||||
if address.get('house_number'):
|
if address.get('house_number'):
|
||||||
@@ -58,30 +59,30 @@ def normalize_osm_result(result: dict) -> dict:
|
|||||||
street_parts.append(address['pedestrian'])
|
street_parts.append(address['pedestrian'])
|
||||||
elif address.get('footway'):
|
elif address.get('footway'):
|
||||||
street_parts.append(address['footway'])
|
street_parts.append(address['footway'])
|
||||||
|
|
||||||
# Handle additional address components
|
# Handle additional address components
|
||||||
suburb = address.get('suburb', '')
|
suburb = address.get('suburb', '')
|
||||||
district = address.get('district', '')
|
district = address.get('district', '')
|
||||||
neighborhood = address.get('neighbourhood', '')
|
neighborhood = address.get('neighbourhood', '')
|
||||||
|
|
||||||
# Build city from available components
|
# Build city from available components
|
||||||
city = (address.get('city') or
|
city = (address.get('city') or
|
||||||
address.get('town') or
|
address.get('town') or
|
||||||
address.get('village') or
|
address.get('village') or
|
||||||
address.get('municipality') or
|
address.get('municipality') or
|
||||||
'')
|
'')
|
||||||
|
|
||||||
# Get detailed state/region information
|
# Get detailed state/region information
|
||||||
state = (address.get('state') or
|
state = (address.get('state') or
|
||||||
address.get('province') or
|
address.get('province') or
|
||||||
address.get('region') or
|
address.get('region') or
|
||||||
'')
|
'')
|
||||||
|
|
||||||
# Get postal code with fallbacks
|
# Get postal code with fallbacks
|
||||||
postal_code = (address.get('postcode') or
|
postal_code = (address.get('postcode') or
|
||||||
address.get('postal_code') or
|
address.get('postal_code') or
|
||||||
'')
|
'')
|
||||||
|
|
||||||
return {
|
return {
|
||||||
'display_name': name or result.get('display_name', ''),
|
'display_name': name or result.get('display_name', ''),
|
||||||
'lat': lat,
|
'lat': lat,
|
||||||
@@ -96,29 +97,30 @@ def normalize_osm_result(result: dict) -> dict:
|
|||||||
'postal_code': postal_code,
|
'postal_code': postal_code,
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
def get_view_mode(request: HttpRequest) -> ViewMode:
|
def get_view_mode(request: HttpRequest) -> ViewMode:
|
||||||
"""Get the current view mode from request, defaulting to grid"""
|
"""Get the current view mode from request, defaulting to grid"""
|
||||||
view_mode = request.GET.get('view_mode', 'grid')
|
view_mode = request.GET.get('view_mode', 'grid')
|
||||||
return cast(ViewMode, 'list' if view_mode == 'list' else '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:
|
def add_park_button(request: HttpRequest) -> HttpResponse:
|
||||||
"""Return the add park button partial template"""
|
"""Return the add park button partial template"""
|
||||||
return render(request, "parks/partials/add_park_button.html")
|
return render(request, "parks/partials/add_park_button.html")
|
||||||
|
|
||||||
|
|
||||||
def park_actions(request: HttpRequest, slug: str) -> HttpResponse:
|
def park_actions(request: HttpRequest, slug: str) -> HttpResponse:
|
||||||
"""Return the park actions partial template"""
|
"""Return the park actions partial template"""
|
||||||
park = get_object_or_404(Park, slug=slug)
|
park = get_object_or_404(Park, slug=slug)
|
||||||
return render(request, "parks/partials/park_actions.html", {"park": park})
|
return render(request, "parks/partials/park_actions.html", {"park": park})
|
||||||
|
|
||||||
|
|
||||||
def get_park_areas(request: HttpRequest) -> HttpResponse:
|
def get_park_areas(request: HttpRequest) -> HttpResponse:
|
||||||
"""Return park areas as options for a select element"""
|
"""Return park areas as options for a select element"""
|
||||||
park_id = request.GET.get('park')
|
park_id = request.GET.get('park')
|
||||||
if not park_id:
|
if not park_id:
|
||||||
return HttpResponse('<option value="">Select a park first</option>')
|
return HttpResponse('<option value="">Select a park first</option>')
|
||||||
|
|
||||||
try:
|
try:
|
||||||
park = Park.objects.get(id=park_id)
|
park = Park.objects.get(id=park_id)
|
||||||
areas = park.areas.all()
|
areas = park.areas.all()
|
||||||
@@ -131,6 +133,7 @@ def get_park_areas(request: HttpRequest) -> HttpResponse:
|
|||||||
except Park.DoesNotExist:
|
except Park.DoesNotExist:
|
||||||
return HttpResponse('<option value="">Invalid park selected</option>')
|
return HttpResponse('<option value="">Invalid park selected</option>')
|
||||||
|
|
||||||
|
|
||||||
def location_search(request: HttpRequest) -> JsonResponse:
|
def location_search(request: HttpRequest) -> JsonResponse:
|
||||||
"""Search for locations using OpenStreetMap Nominatim API"""
|
"""Search for locations using OpenStreetMap Nominatim API"""
|
||||||
query = request.GET.get("q", "")
|
query = request.GET.get("q", "")
|
||||||
@@ -153,7 +156,8 @@ def location_search(request: HttpRequest) -> JsonResponse:
|
|||||||
|
|
||||||
if response.status_code == 200:
|
if response.status_code == 200:
|
||||||
results = response.json()
|
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 = [
|
valid_results = [
|
||||||
r for r in normalized_results
|
r for r in normalized_results
|
||||||
if r["lat"] is not None and r["lon"] is not None
|
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": []})
|
return JsonResponse({"results": []})
|
||||||
|
|
||||||
|
|
||||||
def reverse_geocode(request: HttpRequest) -> JsonResponse:
|
def reverse_geocode(request: HttpRequest) -> JsonResponse:
|
||||||
"""Reverse geocode coordinates using OpenStreetMap Nominatim API"""
|
"""Reverse geocode coordinates using OpenStreetMap Nominatim API"""
|
||||||
try:
|
try:
|
||||||
@@ -217,11 +222,11 @@ class ParkListView(HTMXFilterableMixin, ListView):
|
|||||||
if self.request.htmx:
|
if self.request.htmx:
|
||||||
return ["parks/partials/park_list_item.html"]
|
return ["parks/partials/park_list_item.html"]
|
||||||
return [self.template_name]
|
return [self.template_name]
|
||||||
|
|
||||||
def get_view_mode(self) -> ViewMode:
|
def get_view_mode(self) -> ViewMode:
|
||||||
"""Get the current view mode (grid or list)"""
|
"""Get the current view mode (grid or list)"""
|
||||||
return get_view_mode(self.request)
|
return get_view_mode(self.request)
|
||||||
|
|
||||||
def get_queryset(self) -> QuerySet[Park]:
|
def get_queryset(self) -> QuerySet[Park]:
|
||||||
"""Get base queryset with annotations and apply filters"""
|
"""Get base queryset with annotations and apply filters"""
|
||||||
try:
|
try:
|
||||||
@@ -229,7 +234,7 @@ class ParkListView(HTMXFilterableMixin, ListView):
|
|||||||
except Exception as e:
|
except Exception as e:
|
||||||
messages.error(self.request, f"Error loading parks: {str(e)}")
|
messages.error(self.request, f"Error loading parks: {str(e)}")
|
||||||
queryset = self.model.objects.none()
|
queryset = self.model.objects.none()
|
||||||
|
|
||||||
# Always initialize filterset, even if queryset failed
|
# Always initialize filterset, even if queryset failed
|
||||||
self.filterset = self.get_filter_class()(self.request.GET, queryset=queryset)
|
self.filterset = self.get_filter_class()(self.request.GET, queryset=queryset)
|
||||||
return self.filterset.qs
|
return self.filterset.qs
|
||||||
@@ -243,7 +248,7 @@ class ParkListView(HTMXFilterableMixin, ListView):
|
|||||||
self.request.GET,
|
self.request.GET,
|
||||||
queryset=self.model.objects.none()
|
queryset=self.model.objects.none()
|
||||||
)
|
)
|
||||||
|
|
||||||
context = super().get_context_data(**kwargs)
|
context = super().get_context_data(**kwargs)
|
||||||
context.update({
|
context.update({
|
||||||
'view_mode': self.get_view_mode(),
|
'view_mode': self.get_view_mode(),
|
||||||
@@ -311,6 +316,7 @@ def search_parks(request: HttpRequest) -> HttpResponse:
|
|||||||
response['HX-Trigger'] = 'searchError'
|
response['HX-Trigger'] = 'searchError'
|
||||||
return response
|
return response
|
||||||
|
|
||||||
|
|
||||||
class ParkCreateView(LoginRequiredMixin, CreateView):
|
class ParkCreateView(LoginRequiredMixin, CreateView):
|
||||||
model = Park
|
model = Park
|
||||||
form_class = ParkForm
|
form_class = ParkForm
|
||||||
@@ -324,7 +330,8 @@ class ParkCreateView(LoginRequiredMixin, CreateView):
|
|||||||
data["opening_date"] = data["opening_date"].isoformat()
|
data["opening_date"] = data["opening_date"].isoformat()
|
||||||
if data.get("closing_date"):
|
if data.get("closing_date"):
|
||||||
data["closing_date"] = data["closing_date"].isoformat()
|
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:
|
for field in decimal_fields:
|
||||||
if data.get(field):
|
if data.get(field):
|
||||||
data[field] = str(data[field])
|
data[field] = str(data[field])
|
||||||
@@ -375,7 +382,8 @@ class ParkCreateView(LoginRequiredMixin, CreateView):
|
|||||||
location_type="park",
|
location_type="park",
|
||||||
latitude=form.cleaned_data["latitude"],
|
latitude=form.cleaned_data["latitude"],
|
||||||
longitude=form.cleaned_data["longitude"],
|
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", ""),
|
city=form.cleaned_data.get("city", ""),
|
||||||
state=form.cleaned_data.get("state", ""),
|
state=form.cleaned_data.get("state", ""),
|
||||||
country=form.cleaned_data.get("country", ""),
|
country=form.cleaned_data.get("country", ""),
|
||||||
@@ -389,7 +397,8 @@ class ParkCreateView(LoginRequiredMixin, CreateView):
|
|||||||
Photo.objects.create(
|
Photo.objects.create(
|
||||||
image=photo_file,
|
image=photo_file,
|
||||||
uploaded_by=self.request.user,
|
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,
|
object_id=self.object.id,
|
||||||
)
|
)
|
||||||
uploaded_count += 1
|
uploaded_count += 1
|
||||||
@@ -444,7 +453,8 @@ class ParkUpdateView(LoginRequiredMixin, UpdateView):
|
|||||||
data["opening_date"] = data["opening_date"].isoformat()
|
data["opening_date"] = data["opening_date"].isoformat()
|
||||||
if data.get("closing_date"):
|
if data.get("closing_date"):
|
||||||
data["closing_date"] = data["closing_date"].isoformat()
|
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:
|
for field in decimal_fields:
|
||||||
if data.get(field):
|
if data.get(field):
|
||||||
data[field] = str(data[field])
|
data[field] = str(data[field])
|
||||||
@@ -516,7 +526,8 @@ class ParkUpdateView(LoginRequiredMixin, UpdateView):
|
|||||||
Photo.objects.create(
|
Photo.objects.create(
|
||||||
image=photo_file,
|
image=photo_file,
|
||||||
uploaded_by=self.request.user,
|
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,
|
object_id=self.object.id,
|
||||||
)
|
)
|
||||||
uploaded_count += 1
|
uploaded_count += 1
|
||||||
@@ -651,5 +662,3 @@ class ParkAreaDetailView(
|
|||||||
def get_redirect_url_kwargs(self) -> dict[str, str]:
|
def get_redirect_url_kwargs(self) -> dict[str, str]:
|
||||||
area = cast(ParkArea, self.object)
|
area = cast(ParkArea, self.object)
|
||||||
return {"park_slug": area.park.slug, "area_slug": area.slug}
|
return {"park_slug": area.park.slug, "area_slug": area.slug}
|
||||||
|
|
||||||
|
|
||||||
|
|||||||
Reference in New Issue
Block a user