from django.shortcuts import render, get_object_or_404, redirect from django.http import HttpResponse, HttpResponseBadRequest from django.template.loader import render_to_string from .models import Dinosaur, BackgroundImage from .forms import DinosaurForm from .forms import BackgroundImageForm def is_htmx(request): return request.headers.get('HX-Request') == 'true' def card_list(request): cards = Dinosaur.objects.all() background = BackgroundImage.get_active() if BackgroundImage.objects.exists() else None if is_htmx(request): return render(request, 'cards/_cards_list.html', {'cards': cards, 'background': background}) return render(request, 'cards/list.html', {'cards': cards, 'background': background}) def card_create(request): background = BackgroundImage.get_active() if BackgroundImage.objects.exists() else None backgrounds = BackgroundImage.objects.all() if request.method == 'POST': form = DinosaurForm(request.POST, request.FILES) if form.is_valid(): card = form.save() if is_htmx(request): card_html = render_to_string('cards/_card_item.html', {'card': card, 'background': background}, request=request) # Also return an out-of-band fragment to replace/clear the form container form_html = render_to_string('cards/_form.html', {'form': DinosaurForm(), 'background': background, 'backgrounds': backgrounds}, request=request) oob = f'
{form_html}
' return HttpResponse(card_html + oob) return redirect('cards:list') else: if is_htmx(request): # Return the form as an out-of-band fragment so it updates the form container form_html = render_to_string('cards/_form.html', {'form': form, 'background': background, 'backgrounds': backgrounds}, request=request) oob = f'
{form_html}
' return HttpResponse(oob) else: form = DinosaurForm() return render(request, 'cards/_form.html', {'form': form, 'background': background, 'backgrounds': backgrounds}) def card_edit(request, pk): card = get_object_or_404(Dinosaur, pk=pk) background = BackgroundImage.get_active() if BackgroundImage.objects.exists() else None backgrounds = BackgroundImage.objects.all() if request.method == 'POST': form = DinosaurForm(request.POST, request.FILES, instance=card) if form.is_valid(): card = form.save() if is_htmx(request): card_html = render_to_string('cards/_card_item.html', {'card': card, 'background': background}, request=request) # Clear the form container via OOB so the edit form disappears after successful save oob = '
' return HttpResponse(card_html + oob) return redirect('cards:list') else: if is_htmx(request): form_html = render_to_string('cards/_form.html', {'form': form, 'card': card, 'background': background, 'backgrounds': backgrounds}, request=request) oob = f'
{form_html}
' return HttpResponse(oob) else: form = DinosaurForm(instance=card) return render(request, 'cards/_form.html', {'form': form, 'card': card, 'background': background, 'backgrounds': backgrounds}) def card_delete(request, pk): card = get_object_or_404(Dinosaur, pk=pk) if request.method == 'POST': card.delete() if is_htmx(request): return HttpResponse(status=204) return redirect('cards:list') return HttpResponseBadRequest('Only POST allowed') def background_list(request): """Show existing backgrounds and provide a form to upload a new one.""" backgrounds = BackgroundImage.objects.all() form = BackgroundImageForm() if is_htmx(request): return render(request, 'cards/_backgrounds_list.html', {'backgrounds': backgrounds, 'form': form}) return render(request, 'cards/backgrounds_list.html', {'backgrounds': backgrounds, 'form': form}) def background_create(request): if request.method != 'POST': return HttpResponseBadRequest('Only POST allowed') form = BackgroundImageForm(request.POST, request.FILES) if form.is_valid(): bg = form.save() # If marked active, unset others if bg.is_active: BackgroundImage.objects.exclude(pk=bg.pk).update(is_active=False) if is_htmx(request): # return the updated list fragment and clear the form OOB list_html = render_to_string('cards/_backgrounds_list.html', {'backgrounds': BackgroundImage.objects.all(), 'form': BackgroundImageForm()}, request=request) oob = f'
{render_to_string("cards/_background_form.html", {"form": BackgroundImageForm()}, request=request)}
' return HttpResponse(list_html + oob) return redirect('cards:backgrounds') else: if is_htmx(request): form_html = render_to_string('cards/_background_form.html', {'form': form}, request=request) oob = f'
{form_html}
' return HttpResponse(oob) return render(request, 'cards/backgrounds_list.html', {'backgrounds': BackgroundImage.objects.all(), 'form': form}) def background_activate(request, pk): if request.method != 'POST': return HttpResponseBadRequest('Only POST allowed') bg = get_object_or_404(BackgroundImage, pk=pk) BackgroundImage.objects.update(is_active=False) bg.is_active = True bg.save() if is_htmx(request): list_html = render_to_string('cards/_backgrounds_list.html', {'backgrounds': BackgroundImage.objects.all(), 'form': BackgroundImageForm()}, request=request) return HttpResponse(list_html) return redirect('cards:backgrounds') def background_delete(request, pk): if request.method != 'POST': return HttpResponseBadRequest('Only POST allowed') bg = get_object_or_404(BackgroundImage, pk=pk) bg.delete() if is_htmx(request): return HttpResponse(status=204) return redirect('cards:backgrounds') def preview_card(request, pk): """Render a full preview of a card. HTMX loads the modal fragment into #modal-root.""" card = get_object_or_404(Dinosaur, pk=pk) background = BackgroundImage.get_active() if BackgroundImage.objects.exists() else None if is_htmx(request): return render(request, 'cards/_card_preview.html', {'card': card, 'background': background}) return render(request, 'cards/preview.html', {'card': card, 'background': background})