remove backend

This commit is contained in:
pacnpal
2025-09-21 20:19:12 -04:00
parent 9e724bd795
commit f3c59ad6ff
557 changed files with 1739 additions and 4836 deletions

351
apps/parks/forms.py Normal file
View File

@@ -0,0 +1,351 @@
from django import forms
from decimal import Decimal, InvalidOperation, ROUND_DOWN
from autocomplete.core import register
from autocomplete.shortcuts import ModelAutocomplete
from autocomplete.widgets import AutocompleteWidget
from .models import Park
from .models.location import ParkLocation
@register
class ParkAutocomplete(ModelAutocomplete):
"""Autocomplete for searching parks.
Features:
- Name-based search with partial matching
- Prefetches related owner data
- Applies standard park queryset filtering
- Includes park status and location in results
"""
model = Park
search_attrs = ["name"] # We'll match on park names
class ParkSearchForm(forms.Form):
"""Form for searching parks with autocomplete."""
park = forms.ModelChoiceField(
queryset=Park.objects.all(),
required=False,
widget=AutocompleteWidget(
ac_class=ParkAutocomplete,
attrs={
"class": (
"w-full border-gray-300 rounded-lg form-input "
"dark:border-gray-600 dark:bg-gray-700 dark:text-white"
),
"placeholder": "Search parks...",
},
),
)
class ParkForm(forms.ModelForm):
"""Form for creating and updating Park objects with location support"""
# Location fields
latitude = forms.DecimalField(
max_digits=9,
decimal_places=6,
required=False,
widget=forms.HiddenInput(),
)
longitude = forms.DecimalField(
max_digits=10,
decimal_places=6,
required=False,
widget=forms.HiddenInput(),
)
street_address = forms.CharField(
max_length=255,
required=False,
widget=forms.TextInput(
attrs={
"class": (
"w-full border-gray-300 rounded-lg form-input "
"dark:border-gray-600 dark:bg-gray-700 dark:text-white"
)
}
),
)
city = forms.CharField(
max_length=255,
required=False,
widget=forms.TextInput(
attrs={
"class": (
"w-full border-gray-300 rounded-lg form-input "
"dark:border-gray-600 dark:bg-gray-700 dark:text-white"
)
}
),
)
state = forms.CharField(
max_length=255,
required=False,
widget=forms.TextInput(
attrs={
"class": (
"w-full border-gray-300 rounded-lg form-input "
"dark:border-gray-600 dark:bg-gray-700 dark:text-white"
)
}
),
)
country = forms.CharField(
max_length=255,
required=False,
widget=forms.TextInput(
attrs={
"class": (
"w-full border-gray-300 rounded-lg form-input "
"dark:border-gray-600 dark:bg-gray-700 dark:text-white"
)
}
),
)
postal_code = forms.CharField(
max_length=20,
required=False,
widget=forms.TextInput(
attrs={
"class": (
"w-full border-gray-300 rounded-lg form-input "
"dark:border-gray-600 dark:bg-gray-700 dark:text-white"
)
}
),
)
class Meta:
model = Park
fields = [
"name",
"description",
"operator",
"property_owner",
"status",
"opening_date",
"closing_date",
"operating_season",
"size_acres",
"website",
# Location fields handled separately
"latitude",
"longitude",
"street_address",
"city",
"state",
"country",
"postal_code",
]
widgets = {
"name": forms.TextInput(
attrs={
"class": (
"w-full border-gray-300 rounded-lg form-input "
"dark:border-gray-600 dark:bg-gray-700 dark:text-white"
)
}
),
"description": forms.Textarea(
attrs={
"class": (
"w-full border-gray-300 rounded-lg form-textarea "
"dark:border-gray-600 dark:bg-gray-700 dark:text-white"
),
"rows": 2,
}
),
"operator": forms.Select(
attrs={
"class": (
"w-full border-gray-300 rounded-lg form-select "
"dark:border-gray-600 dark:bg-gray-700 dark:text-white"
)
}
),
"property_owner": forms.Select(
attrs={
"class": (
"w-full border-gray-300 rounded-lg form-select "
"dark:border-gray-600 dark:bg-gray-700 dark:text-white"
)
}
),
"status": forms.Select(
attrs={
"class": (
"w-full border-gray-300 rounded-lg form-select "
"dark:border-gray-600 dark:bg-gray-700 dark:text-white"
)
}
),
"opening_date": forms.DateInput(
attrs={
"type": "date",
"class": (
"w-full border-gray-300 rounded-lg form-input "
"dark:border-gray-600 dark:bg-gray-700 dark:text-white"
),
}
),
"closing_date": forms.DateInput(
attrs={
"type": "date",
"class": (
"w-full border-gray-300 rounded-lg form-input "
"dark:border-gray-600 dark:bg-gray-700 dark:text-white"
),
}
),
"operating_season": forms.TextInput(
attrs={
"class": (
"w-full border-gray-300 rounded-lg form-input "
"dark:border-gray-600 dark:bg-gray-700 dark:text-white"
),
"placeholder": "e.g., Year-round, Summer only, etc.",
}
),
"size_acres": forms.NumberInput(
attrs={
"class": (
"w-full border-gray-300 rounded-lg form-input "
"dark:border-gray-600 dark:bg-gray-700 dark:text-white"
),
"step": "0.01",
"min": "0",
}
),
"website": forms.URLInput(
attrs={
"class": (
"w-full border-gray-300 rounded-lg form-input "
"dark:border-gray-600 dark:bg-gray-700 dark:text-white"
),
"placeholder": "https://example.com",
}
),
}
def __init__(self, *args, **kwargs):
super().__init__(*args, **kwargs)
# Pre-fill location fields if editing existing park
if self.instance and self.instance.pk and self.instance.location.exists():
location = self.instance.location.first()
self.fields["latitude"].initial = location.latitude
self.fields["longitude"].initial = location.longitude
self.fields["street_address"].initial = location.street_address
self.fields["city"].initial = location.city
self.fields["state"].initial = location.state
self.fields["country"].initial = location.country
self.fields["postal_code"].initial = location.postal_code
def clean_latitude(self):
latitude = self.cleaned_data.get("latitude")
if latitude is not None:
try:
# Convert to Decimal for precise handling
latitude = Decimal(str(latitude))
# Round to exactly 6 decimal places
latitude = latitude.quantize(Decimal("0.000001"), rounding=ROUND_DOWN)
# Validate range
if latitude < -90 or latitude > 90:
raise forms.ValidationError(
"Latitude must be between -90 and 90 degrees."
)
# Convert to string to preserve exact decimal places
return str(latitude)
except (InvalidOperation, TypeError) as e:
raise forms.ValidationError("Invalid latitude value.") from e
return latitude
def clean_longitude(self):
longitude = self.cleaned_data.get("longitude")
if longitude is not None:
try:
# Convert to Decimal for precise handling
longitude = Decimal(str(longitude))
# Round to exactly 6 decimal places
longitude = longitude.quantize(Decimal("0.000001"), rounding=ROUND_DOWN)
# Validate range
if longitude < -180 or longitude > 180:
raise forms.ValidationError(
"Longitude must be between -180 and 180 degrees."
)
# Convert to string to preserve exact decimal places
return str(longitude)
except (InvalidOperation, TypeError) as e:
raise forms.ValidationError("Invalid longitude value.") from e
return longitude
def save(self, commit=True):
park = super().save(commit=False)
# Prepare location data
location_data = {
"name": park.name,
"location_type": "park",
"latitude": self.cleaned_data.get("latitude"),
"longitude": self.cleaned_data.get("longitude"),
"street_address": self.cleaned_data.get("street_address"),
"city": self.cleaned_data.get("city"),
"state": self.cleaned_data.get("state"),
"country": self.cleaned_data.get("country"),
"postal_code": self.cleaned_data.get("postal_code"),
}
# Handle location: update if exists, create if not
try:
park_location = park.location
# Update existing location
for key, value in location_data.items():
if key in ["latitude", "longitude"] and value:
continue # Handle coordinates separately
if hasattr(park_location, key):
setattr(park_location, key, value)
# Handle coordinates if provided
if "latitude" in location_data and "longitude" in location_data:
if location_data["latitude"] and location_data["longitude"]:
park_location.set_coordinates(
float(location_data["latitude"]),
float(location_data["longitude"]),
)
park_location.save()
except ParkLocation.DoesNotExist:
# Create new ParkLocation
coordinates_data = {}
if "latitude" in location_data and "longitude" in location_data:
if location_data["latitude"] and location_data["longitude"]:
coordinates_data = {
"latitude": float(location_data["latitude"]),
"longitude": float(location_data["longitude"]),
}
# Remove coordinate fields from location_data for creation
creation_data = {
k: v
for k, v in location_data.items()
if k not in ["latitude", "longitude"]
}
creation_data.setdefault("country", "USA")
park_location = ParkLocation.objects.create(park=park, **creation_data)
if coordinates_data:
park_location.set_coordinates(
coordinates_data["latitude"], coordinates_data["longitude"]
)
park_location.save()
if commit:
park.save()
return park