[birds] Add birding location scrobbling
This commit is contained in:
85
vrobbler/apps/birds/forms.py
Normal file
85
vrobbler/apps/birds/forms.py
Normal file
@ -0,0 +1,85 @@
|
||||
import json
|
||||
|
||||
from birds.models import Bird, BirdSightingEntry
|
||||
from django import forms
|
||||
|
||||
|
||||
class BirdSightingsWidget(forms.Widget):
|
||||
template_name = "birds/bird_sightings_widget.html"
|
||||
|
||||
class Media:
|
||||
js = ("birds/bird_sightings.js",)
|
||||
|
||||
def value_from_datadict(self, data, files, name):
|
||||
bird_ids = data.getlist(f"{name}_bird_id")
|
||||
quantities = data.getlist(f"{name}_quantity")
|
||||
notes = data.getlist(f"{name}_sighting_notes")
|
||||
return {
|
||||
"bird_id": bird_ids,
|
||||
"quantity": quantities,
|
||||
"sighting_notes": notes,
|
||||
}
|
||||
|
||||
def get_context(self, name, value, attrs):
|
||||
context = super().get_context(name, value, attrs)
|
||||
sightings = []
|
||||
if value:
|
||||
if isinstance(value, str):
|
||||
try:
|
||||
value = json.loads(value)
|
||||
except (json.JSONDecodeError, TypeError):
|
||||
value = []
|
||||
for item in (value or []):
|
||||
if isinstance(item, dict):
|
||||
sightings.append(item)
|
||||
elif isinstance(item, BirdSightingEntry):
|
||||
sightings.append(item.asdict)
|
||||
context["widget"]["sightings"] = sightings
|
||||
context["widget"]["birds"] = Bird.objects.all().order_by("common_name")
|
||||
return context
|
||||
|
||||
|
||||
class BirdSightingsField(forms.Field):
|
||||
widget = BirdSightingsWidget
|
||||
|
||||
def clean(self, value):
|
||||
if not value:
|
||||
return None
|
||||
result = []
|
||||
bird_ids = value.get("bird_id", []) if isinstance(value, dict) else []
|
||||
quantities = value.get("quantity", []) if isinstance(value, dict) else []
|
||||
notes_list = (
|
||||
value.get("sighting_notes", []) if isinstance(value, dict) else []
|
||||
)
|
||||
|
||||
if isinstance(bird_ids, list):
|
||||
for i, bird_id in enumerate(bird_ids):
|
||||
if not bird_id:
|
||||
continue
|
||||
try:
|
||||
bird_id = int(bird_id)
|
||||
quantity = int(quantities[i]) if i < len(quantities) else 1
|
||||
except (ValueError, TypeError, IndexError):
|
||||
continue
|
||||
note = notes_list[i] if i < len(notes_list) else ""
|
||||
entry = BirdSightingEntry(
|
||||
bird_id=bird_id,
|
||||
quantity=quantity,
|
||||
sighting_notes=note or None,
|
||||
)
|
||||
result.append(entry.asdict)
|
||||
elif bird_ids:
|
||||
try:
|
||||
bird_id = int(bird_ids)
|
||||
quantity = int(quantities) if quantities else 1
|
||||
except (ValueError, TypeError):
|
||||
raise forms.ValidationError("Invalid bird sighting data")
|
||||
note = notes_list if notes_list else ""
|
||||
entry = BirdSightingEntry(
|
||||
bird_id=bird_id,
|
||||
quantity=quantity,
|
||||
sighting_notes=note or None,
|
||||
)
|
||||
result.append(entry.asdict)
|
||||
|
||||
return result if result else None
|
||||
Reference in New Issue
Block a user