from django import forms from django.urls import reverse_lazy from .models import Park from cities_light.models import Country, Region, City class LocationFilterForm(forms.Form): country = forms.CharField( 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', 'placeholder': 'Select or type a country', 'hx-get': reverse_lazy('parks:country_search'), 'hx-trigger': 'focus, input', 'hx-target': '#country-results', 'autocomplete': 'off' }) ) region = forms.CharField( 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', 'placeholder': 'Select or type a region/state', 'hx-get': reverse_lazy('parks:region_search'), 'hx-trigger': 'focus, input', 'hx-target': '#region-results', 'autocomplete': 'off' }) ) city = forms.CharField( 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', 'placeholder': 'Select or type a city', 'hx-get': reverse_lazy('parks:city_search'), 'hx-trigger': 'focus, input', 'hx-target': '#city-results', 'autocomplete': 'off' }) ) class ParkForm(forms.ModelForm): # Hidden fields for actual model relations country = forms.ModelChoiceField(queryset=Country.objects.all(), required=True, widget=forms.HiddenInput()) region = forms.ModelChoiceField(queryset=Region.objects.all(), required=False, widget=forms.HiddenInput()) city = forms.ModelChoiceField(queryset=City.objects.all(), required=False, widget=forms.HiddenInput()) # Visible fields for Alpine.js country_name = forms.CharField( label="Country", required=True, 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', 'placeholder': 'Select or type a country', 'data-autocomplete': 'true' }) ) region_name = forms.CharField( label="Region/State", 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', 'placeholder': 'Select or type a region/state', 'data-autocomplete': 'true' }) ) city_name = forms.CharField( label="City", 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', 'placeholder': 'Select or type a city', 'data-autocomplete': 'true' }) ) class Meta: model = Park fields = ['name', 'description', 'owner', 'status', 'opening_date', 'closing_date', 'operating_season', 'size_acres', 'website', 'country', 'region', 'city'] 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': 4 }), '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) instance = kwargs.get('instance') if instance: try: if instance.country: self.fields['country_name'].initial = instance.country.name self.fields['country'].initial = instance.country except Country.DoesNotExist: pass try: if instance.region: self.fields['region_name'].initial = instance.region.name self.fields['region'].initial = instance.region except Region.DoesNotExist: pass try: if instance.city: self.fields['city_name'].initial = instance.city.name self.fields['city'].initial = instance.city except City.DoesNotExist: pass def clean(self): cleaned_data = super().clean() country_name = cleaned_data.get('country_name') region_name = cleaned_data.get('region_name') city_name = cleaned_data.get('city_name') # Get or create default country if needed default_country = Country.objects.first() if not default_country: default_country = Country.objects.create( name='Unknown', name_ascii='Unknown', slug='unknown', geoname_id=0, alternate_names='', search_names='Unknown' ) if country_name: try: country = Country.objects.get(name__iexact=country_name) cleaned_data['country'] = country except Country.DoesNotExist: cleaned_data['country'] = default_country else: raise forms.ValidationError("Country is required") if region_name and cleaned_data.get('country'): try: region = Region.objects.get( name__iexact=region_name, country=cleaned_data['country'] ) cleaned_data['region'] = region except Region.DoesNotExist: cleaned_data['region'] = None if city_name and cleaned_data.get('region'): try: city = City.objects.get( name__iexact=city_name, region=cleaned_data['region'] ) cleaned_data['city'] = city except City.DoesNotExist: cleaned_data['city'] = None return cleaned_data