diff --git a/cards/templates/cards/_form.html b/cards/templates/cards/_form.html index 7e016a2..ef391f0 100644 --- a/cards/templates/cards/_form.html +++ b/cards/templates/cards/_form.html @@ -131,19 +131,47 @@
-
{{ form.speed }}
+
+
+
{{ form.speed }}
+
+ km/h +
+
+
-
{{ form.weight }}
+
+
+
{{ form.weight }}
+
+ kg +
+
+
-
{{ form.intelligence }}
+
+
+
{{ form.intelligence }}
+
+ score +
+
+
-
{{ form.height }}
+
+
+
{{ form.height }}
+
+ m +
+
+
diff --git a/cards/templates/cards/bulk_edit.html b/cards/templates/cards/bulk_edit.html index dadc6ba..bb04ac7 100644 --- a/cards/templates/cards/bulk_edit.html +++ b/cards/templates/cards/bulk_edit.html @@ -2,13 +2,30 @@ {% block content %}
-

Cards overview — bulk edit

Edit multiple cards inline and save changes in one go.

+ +
{% csrf_token %} - +
+
@@ -35,10 +52,30 @@ - - - - + + + + {% endfor %} @@ -61,16 +98,37 @@ {% endfor %} - - - - + + + + {% endfor %} {% endif %} -
Preview {{ form.name }} {{ form.background }}{{ form.speed }}{{ form.weight }}{{ form.height }}{{ form.intelligence }} +
+
{{ form.speed }}
+ +
+
+
+
{{ form.weight }}
+ +
+
+
+
{{ form.height }}
+ +
+
+
+
{{ form.intelligence }}
+ +
+
ID: {{ form.instance.pk }}
+
+
+ +
+
+
+
+ +
+
+
+
+ +
+
+
+
+ +
+
ID: {{ card.pk }}
+ +
@@ -79,6 +137,5 @@
-
{% endblock %} diff --git a/cards/views.py b/cards/views.py index b9e3946..0c5de6d 100644 --- a/cards/views.py +++ b/cards/views.py @@ -1,6 +1,7 @@ from django.shortcuts import render, get_object_or_404, redirect from django.http import HttpResponse, HttpResponseBadRequest from django.template.loader import render_to_string +import os from .models import Dinosaur, BackgroundImage from .forms import DinosaurBulkFormSet from .forms import DinosaurForm @@ -26,7 +27,16 @@ def card_create(request): if request.method == 'POST': form = DinosaurForm(request.POST, request.FILES) if form.is_valid(): - card = form.save() + # Save instance with commit=False so we can set a default name + # from the uploaded image filename when the name is empty. + card = form.save(commit=False) + if not card.name: + image_file = form.cleaned_data.get('image') + if image_file and getattr(image_file, 'name', None): + base = os.path.splitext(image_file.name)[0] + # replace separators and title-case for a nicer default + card.name = base.replace('_', ' ').replace('-', ' ').strip().title() + card.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 @@ -53,7 +63,15 @@ def card_edit(request, pk): if request.method == 'POST': form = DinosaurForm(request.POST, request.FILES, instance=card) if form.is_valid(): - card = form.save() + # Save with commit=False to allow setting a default name from an + # uploaded image if the instance has no name. + card = form.save(commit=False) + if not card.name: + image_file = form.cleaned_data.get('image') + if image_file and getattr(image_file, 'name', None): + base = os.path.splitext(image_file.name)[0] + card.name = base.replace('_', ' ').replace('-', ' ').strip().title() + card.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 @@ -150,17 +168,22 @@ def cards_overview(request): """Overview page showing all cards in a table for quick edits.""" backgrounds = BackgroundImage.objects.all() qs = Dinosaur.objects.order_by('name') - formset = None - return render(request, 'cards/bulk_edit.html', {'cards': qs, 'backgrounds': backgrounds}) + # Use a modelformset so the template renders the management form + formset = DinosaurBulkFormSet(queryset=qs) + return render(request, 'cards/bulk_edit.html', {'formset': formset, 'backgrounds': backgrounds}) def cards_bulk_update(request): """Handle POST from the bulk edit formset and save changes.""" if request.method != 'POST': - return HttpResponseBadRequest('Only POST allowed') + # If someone visits the bulk-update URL with GET, redirect them back + # to the overview page instead of returning a 400 Bad Request. + return redirect('cards:overview') formset = None + qs = Dinosaur.objects.order_by('name') try: - formset = DinosaurBulkFormSet(request.POST) + # Pass the same queryset so management/initial forms align with the rendered formset + formset = DinosaurBulkFormSet(request.POST, queryset=qs) except Exception: return HttpResponseBadRequest('Invalid submission') if formset.is_valid(): diff --git a/db.sqlite3 b/db.sqlite3 index 1fca01e..fd50e69 100644 Binary files a/db.sqlite3 and b/db.sqlite3 differ diff --git a/media/dinosaurs/Barosaurus.png b/media/dinosaurs/Barosaurus.png new file mode 100644 index 0000000..131ec43 Binary files /dev/null and b/media/dinosaurs/Barosaurus.png differ diff --git a/media/dinosaurs/Diplodocus.png b/media/dinosaurs/Diplodocus.png new file mode 100644 index 0000000..453087e Binary files /dev/null and b/media/dinosaurs/Diplodocus.png differ diff --git a/media/dinosaurs/ankylosaurus.png b/media/dinosaurs/ankylosaurus.png new file mode 100644 index 0000000..e803def Binary files /dev/null and b/media/dinosaurs/ankylosaurus.png differ diff --git a/templates/cards/_form.html b/templates/cards/_form.html index 4730183..6203f9a 100644 --- a/templates/cards/_form.html +++ b/templates/cards/_form.html @@ -112,6 +112,17 @@ if(!label) return; if(fi.files.length === 0) label.textContent = 'No file chosen'; else label.textContent = fi.files.length > 1 ? fi.files.length + ' files selected' : fi.files[0].name; + try { + const nameInput = formRoot.querySelector('input[name="name"]'); + if(nameInput && (!nameInput.value || nameInput.value.trim() === '')){ + const f = fi.files && fi.files[0]; + if(f && f.name){ + const base = f.name.replace(/\.[^/.]+$/, ''); + const title = base.replace(/[_-]+/g, ' ').split(/\s+/).map(function(w){ return w.length? (w.charAt(0).toUpperCase() + w.slice(1)) : ''; }).join(' ').trim(); + if(title) nameInput.value = title; + } + } + }catch(e){ /* ignore UI enhancement errors */ } }); const outerLabel = fi.closest('.file').querySelector('.file-label'); if(outerLabel && !outerLabel.contains(fi)){ diff --git a/templates/cards/bulk_edit.html b/templates/cards/bulk_edit.html index dadc6ba..7fc9ed6 100644 --- a/templates/cards/bulk_edit.html +++ b/templates/cards/bulk_edit.html @@ -2,13 +2,29 @@ {% block content %}
-

Cards overview — bulk edit

Edit multiple cards inline and save changes in one go.

+ +
{% csrf_token %} - +
+
@@ -61,16 +77,37 @@ {% endfor %} - - - - + + + + {% endfor %} {% endif %} -
Preview +
+
+ +
+
+
+
+ +
+
+
+
+ +
+
+
+
+ +
+
ID: {{ card.pk }}
+ +
@@ -79,6 +116,5 @@
-
{% endblock %}