aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorMatthew Lemon <y@yulqen.org>2024-05-26 20:47:03 +0100
committerMatthew Lemon <y@yulqen.org>2024-05-26 20:47:03 +0100
commitd421e56e0924487861e6cf5300f462c9e66fd376 (patch)
tree5340955b351772dfc9ec38c7a80035b5781cc93a
parent610177be35ec791edae9577f104d0132f2a28364 (diff)
Correctly handles the unique constraint on feature_slot
-rw-r--r--pyblackbird_cc/resources/forms.py6
-rw-r--r--pyblackbird_cc/resources/migrations/0009_alter_resource_feature_slot.py18
-rw-r--r--pyblackbird_cc/resources/models.py22
-rw-r--r--pyblackbird_cc/resources/views.py76
-rw-r--r--pyblackbird_cc/templates/resources/create_featured_resource.html35
5 files changed, 88 insertions, 69 deletions
diff --git a/pyblackbird_cc/resources/forms.py b/pyblackbird_cc/resources/forms.py
index ca38640..d0fb001 100644
--- a/pyblackbird_cc/resources/forms.py
+++ b/pyblackbird_cc/resources/forms.py
@@ -56,7 +56,8 @@ class ResourceCreateForm(forms.Form):
card_description = forms.CharField(
max_length=1000,
widget=forms.Textarea,
- help_text="If you enter text here, it will be used in the 'card' description box on the home page. Max 1000 characters.",
+ help_text=("If you enter text here, it will be used in the 'card' description "
+ "box on the home page. Max 1000 characters."),
)
resource_type = forms.ModelChoiceField(queryset=ResourceType.objects.all())
age_range = forms.ChoiceField(
@@ -111,7 +112,8 @@ class ResourceCreateForm(forms.Form):
min_value=1,
max_value=3,
required=False,
- help_text="Please enter either 1, 2 or 3 here. This will dictate where on the page this resource will feature on the main list page.",
+ help_text=("Please enter either 1, 2 or 3 here. This will dictate where on the page "
+ "this resource will feature on the main list page."),
)
def clean_thumbnail_files(self):
diff --git a/pyblackbird_cc/resources/migrations/0009_alter_resource_feature_slot.py b/pyblackbird_cc/resources/migrations/0009_alter_resource_feature_slot.py
new file mode 100644
index 0000000..ca082d4
--- /dev/null
+++ b/pyblackbird_cc/resources/migrations/0009_alter_resource_feature_slot.py
@@ -0,0 +1,18 @@
+# Generated by Django 5.0.4 on 2024-05-26 18:17
+
+from django.db import migrations, models
+
+
+class Migration(migrations.Migration):
+
+ dependencies = [
+ ('resources', '0008_alter_resource_card_description'),
+ ]
+
+ operations = [
+ migrations.AlterField(
+ model_name='resource',
+ name='feature_slot',
+ field=models.IntegerField(blank=True, choices=[(1, 1), (2, 2), (3, 3)], default=0, null=True, unique=True),
+ ),
+ ]
diff --git a/pyblackbird_cc/resources/models.py b/pyblackbird_cc/resources/models.py
index 0d1bbe3..33fd678 100644
--- a/pyblackbird_cc/resources/models.py
+++ b/pyblackbird_cc/resources/models.py
@@ -60,7 +60,8 @@ class Resource(models.Model):
max_length=1000,
blank=True,
default="",
- help_text="If you enter text here, it will be used in the 'card' description box on the home page. Max 1000 characters.",
+ help_text=("If you enter text here, it will be used in the 'card' "
+ "description box on the home page. Max 1000 characters."),
)
age_range = models.CharField(
max_length=20,
@@ -80,7 +81,7 @@ class Resource(models.Model):
],
)
feature_slot = models.IntegerField(
- choices=((0, 0), (1, 1), (2, 2), (3, 3)), unique=True, null=True, blank=True, default=0,
+ choices=((1, 1), (2, 2), (3, 3)), unique=True, null=True, blank=True, default=0,
)
created_at = models.DateTimeField(auto_now_add=True)
updated_at = models.DateTimeField(auto_now=True)
@@ -94,8 +95,7 @@ class Resource(models.Model):
def get_pdf_snapshot_file_names(self):
rs = self.pdf_resources.all()
sh = [sh for sh in rs.values_list("pdf_page_snapshots__file_name", flat=True)]
- out = [s for s in sh if s]
- return out
+ return [s for s in sh if s]
class ResourceType(models.Model):
@@ -151,17 +151,3 @@ class PDFPageSnapshot(models.Model):
def __str__(self):
return self.name
-
-
-# class FeatureResource(models.Model):
-# resource = models.ForeignKey(
-# "Resource",
-# on_delete=models.CASCADE,
-# null=False,
-# related_name="feature_resources",
-# )
-# slot = models.IntegerField(null=False, choices=[(1, 1), (2, 2), (3, 3)])
-# description = models.CharField(max_length=255, null=False)
-#
-# def __str__(self):
-# return f"{self.resource.name} as a feature in slot {self.slot}"
diff --git a/pyblackbird_cc/resources/views.py b/pyblackbird_cc/resources/views.py
index ea8953f..667fb0d 100644
--- a/pyblackbird_cc/resources/views.py
+++ b/pyblackbird_cc/resources/views.py
@@ -8,7 +8,9 @@ import boto3
from botocore.exceptions import ClientError
from botocore.utils import Path
from django.conf import settings
+from django.contrib import messages
from django.contrib.auth.decorators import login_required
+from django.db import IntegrityError
from django.db import transaction
from django.shortcuts import get_object_or_404
from django.shortcuts import redirect
@@ -216,6 +218,7 @@ def create_metadata(
yield metadata, snapshot_images
+#FIXME: Can't find a caller for this - delete it
@transaction.atomic
def create_resource_objects(resource, metadata_generator, thumbnail_files):
for metadata, snapshot_images in metadata_generator:
@@ -255,48 +258,53 @@ def create_resource(request):
feature_slot = form.cleaned_data["feature_slot"]
try:
- resource = Resource.objects.create(
- name=name,
- description=description,
- card_description=card_description,
- resource_type=resource_type,
- age_range=age_range,
- curriculum=curriculum,
- main_resource_category=main_resource_category,
- additional_resource_category=additional_resource_category,
- feature_slot=feature_slot,
- )
-
- metadata_generator = create_metadata(pdf_files)
- snapshotted_pages = []
-
- for metadata, snapshot_images in metadata_generator:
- pdf_resource = PDFResource.objects.create(
- resource=resource,
- file_name=os.path.basename(metadata.file_name),
- file_size=metadata.file_size,
+ with transaction.atomic():
+ resource = Resource.objects.create(
+ name=name,
+ description=description,
+ card_description=card_description,
+ resource_type=resource_type,
+ age_range=age_range,
+ curriculum=curriculum,
+ main_resource_category=main_resource_category,
+ additional_resource_category=additional_resource_category,
+ feature_slot=feature_slot,
)
- for snapshot_image in snapshot_images:
- PDFPageSnapshot.objects.create(
- name="test",
- file_name=os.path.basename(snapshot_image),
- pdf_file=pdf_resource,
+ metadata_generator = create_metadata(pdf_files)
+ snapshotted_pages = []
+
+ for metadata, snapshot_images in metadata_generator:
+ pdf_resource = PDFResource.objects.create(
+ resource=resource,
+ file_name=os.path.basename(metadata.file_name),
+ file_size=metadata.file_size,
)
- snapshotted_pages.append(snapshot_images)
+ for snapshot_image in snapshot_images:
+ PDFPageSnapshot.objects.create(
+ name="test",
+ file_name=os.path.basename(snapshot_image),
+ pdf_file=pdf_resource,
+ )
+
+ snapshotted_pages.append(snapshot_images)
- resource.thumbnail_filenames = [f.name for f in thumbnail_files]
- resource.save()
+ resource.thumbnail_filenames = [f.name for f in thumbnail_files]
+ resource.save()
- # Reset the file pointers for pdf_files
- for pdf_file in pdf_files:
- pdf_file.seek(0)
+ # Reset the file pointers for pdf_files
+ for pdf_file in pdf_files:
+ pdf_file.seek(0)
- if not upload_to_s3(pdf_files, thumbnail_files, snapshotted_pages):
- raise Exception("Error uploading files to S3")
+ if not upload_to_s3(pdf_files, thumbnail_files, snapshotted_pages):
+ raise Exception("Error uploading files to S3")
- return redirect("resources:resource_detail", resource_id=resource.id)
+ return redirect("resources:resource_detail", resource_id=resource.id)
+ except IntegrityError:
+ slot = form.cleaned_data["feature_slot"]
+ messages.add_message(request, messages.ERROR, f"Feature slot {slot} is already "
+ "in use. Quit this form and remove from existing resource.")
except Exception:
logger.exception("Error creating resource")
form.add_error(None, "An error occurred while creating the resource.")
diff --git a/pyblackbird_cc/templates/resources/create_featured_resource.html b/pyblackbird_cc/templates/resources/create_featured_resource.html
index e98b2ba..19022fc 100644
--- a/pyblackbird_cc/templates/resources/create_featured_resource.html
+++ b/pyblackbird_cc/templates/resources/create_featured_resource.html
@@ -1,21 +1,26 @@
{% extends "base.html" %}
-{% load static %}
-{% block title %}Add featured resource{% endblock title %}
+{% load static %}
+{% block title %}
+ Add featured resource
+{% endblock title %}
{% block content %}
-
-{% if request.user.is_authenticated and request.user.is_staff %}
- <div class="row d-flex justify-content-center">
- <div class="col bg-light mt-lg-4 p-4 border border-success border-opacity-25 rounded">
- <h2>Configure featured resources</h2>
- <p>You can select three resources to be "featured" on the main page</p>
+ {% if messages %}
+ <ul class="messages">
+ {% for message in messages %}
+ <li {% if message.tags %}class="{{ message.tags }}"{% endif %}>{{ message }}</li>
+ {% endfor %}
+ </ul>
+ {% endif %}
+ {% if request.user.is_authenticated and request.user.is_staff %}
+ <div class="row d-flex justify-content-center">
+ <div class="col bg-light mt-lg-4 p-4 border border-success border-opacity-25 rounded">
+ <h2>Configure featured resources</h2>
+ <p>You can select three resources to be "featured" on the main page</p>
+ </div>
</div>
- </div>
-{% else %}
- <p>You must be a super-user to access this page.</p>
-{% endif %}
-
-
+ {% else %}
+ <p>You must be a super-user to access this page.</p>
+ {% endif %}
{% endblock content %}
-