from datetime import date from django.shortcuts import render, get_object_or_404, redirect from django.views.decorators.csrf import ensure_csrf_cookie from django.views.decorators.http import require_POST from plants.models import Plant, Species, PruningLog, PlantPhoto from plants.forms import PlantForm, PruningLogForm from plants.utils.pruning import pruning_status def plant_list(request): qs = Plant.objects.select_related('species', 'location').all() q = request.GET.get('q', '') indoor_filter = request.GET.get('filter', '') if q: qs = qs.filter(name__icontains=q) | qs.filter(location__name__icontains=q) if indoor_filter == 'indoor': qs = qs.filter(is_indoor=True) elif indoor_filter == 'outdoor': qs = qs.filter(is_indoor=False) template = ( 'plants/partials/plant_list_results.html' if request.htmx else 'plants/plant_list.html' ) return render(request, template, {'plants': qs, 'q': q, 'filter': indoor_filter}) def plant_detail(request, pk): plant = get_object_or_404( Plant.objects.select_related('species', 'location').prefetch_related('pruning_logs', 'photos'), pk=pk, ) today = date.today() return render(request, 'plants/plant_detail.html', { 'plant': plant, 'pruning_status': pruning_status(plant, today), 'log_form': PruningLogForm(initial={'pruned_on': today}), 'today': today, }) @require_POST def log_pruning(request, pk): plant = get_object_or_404( Plant.objects.prefetch_related('pruning_logs'), pk=pk ) form = PruningLogForm(request.POST) if form.is_valid(): log = form.save(commit=False) log.plant = plant log.save() today = date.today() return render(request, 'plants/partials/pruning_strip.html', { 'plant': plant, 'pruning_status': pruning_status(plant, today), 'log_form': PruningLogForm(initial={'pruned_on': today}), }) @ensure_csrf_cookie def plant_add(request): species_id = request.GET.get('species_id') or request.POST.get('species_id') species = None if species_id and species_id != 'skip': species = get_object_or_404(Species, pk=species_id) if species_id is None and request.method == 'GET': return render(request, 'plants/species_search.html') if request.method == 'POST': form = PlantForm(request.POST, request.FILES) if form.is_valid(): plant = form.save(commit=False) plant.species = species plant.save() return redirect('plant_detail', pk=plant.pk) else: initial = {'bloom_months': species.bloom_months} if species else {} form = PlantForm(initial=initial) return render(request, 'plants/plant_form.html', { 'form': form, 'species': species, 'species_id': species_id, 'title': 'Add Plant', }) def plant_edit(request, pk): plant = get_object_or_404(Plant, pk=pk) if request.method == 'POST': form = PlantForm(request.POST, request.FILES, instance=plant) if form.is_valid(): form.save() return redirect('plant_detail', pk=plant.pk) else: form = PlantForm(instance=plant) return render(request, 'plants/plant_form.html', { 'form': form, 'plant': plant, 'title': 'Edit Plant', }) def plant_delete(request, pk): plant = get_object_or_404(Plant, pk=pk) if request.method == 'POST': plant.delete() return redirect('plant_list') return render(request, 'plants/plant_confirm_delete.html', {'plant': plant}) @require_POST def upload_photo(request, pk): plant = get_object_or_404(Plant.objects.prefetch_related('photos'), pk=pk) if request.FILES.get('image'): PlantPhoto.objects.create(plant=plant, image=request.FILES['image']) return render(request, 'plants/partials/photo_gallery.html', {'plant': plant}) @require_POST def set_thumbnail(request, photo_pk): photo = get_object_or_404(PlantPhoto, pk=photo_pk) PlantPhoto.objects.filter(plant=photo.plant).update(is_thumbnail=False) photo.is_thumbnail = True photo.save(update_fields=['is_thumbnail']) plant = Plant.objects.prefetch_related('photos').get(pk=photo.plant_id) return render(request, 'plants/partials/photo_gallery.html', {'plant': plant}) @require_POST def delete_photo(request, photo_pk): photo = get_object_or_404(PlantPhoto, pk=photo_pk) plant = Plant.objects.prefetch_related('photos').get(pk=photo.plant_id) photo.image.delete(save=False) photo.delete() plant.refresh_from_db() plant = Plant.objects.prefetch_related('photos').get(pk=plant.pk) return render(request, 'plants/partials/photo_gallery.html', {'plant': plant})