from django import forms from decimal import Decimal, InvalidOperation, ROUND_DOWN from .models import Park class ParkForm(forms.ModelForm): """Form for creating and updating Park objects with location support""" class Meta: model = Park fields = [ "name", "description", "owner", "status", "opening_date", "closing_date", "operating_season", "size_acres", "website", "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, } ), "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", } ), # Location fields "latitude": forms.HiddenInput(), "longitude": forms.HiddenInput(), "street_address": 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.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.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.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.TextInput( attrs={ "class": "w-full border-gray-300 rounded-lg form-input dark:border-gray-600 dark:bg-gray-700 dark:text-white" } ), } 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): raise forms.ValidationError("Invalid latitude value.") 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): raise forms.ValidationError("Invalid longitude value.") return longitude