From 8b6556fd10b39e2308610bddd3c215fe3931bf03 Mon Sep 17 00:00:00 2001 From: Ed Woodward Date: Mon, 14 Mar 2022 15:30:04 -0500 Subject: [PATCH 1/3] GiveBanner snippet --- snippets/migrations/0019_givebanner.py | 33 +++++++++++++++++++++++++ snippets/models.py | 34 ++++++++++++++++++++++++++ snippets/serializers.py | 11 ++++++++- snippets/tests.py | 9 ++++++- snippets/urls.py | 1 + snippets/views.py | 9 +++++-- 6 files changed, 93 insertions(+), 4 deletions(-) create mode 100644 snippets/migrations/0019_givebanner.py diff --git a/snippets/migrations/0019_givebanner.py b/snippets/migrations/0019_givebanner.py new file mode 100644 index 000000000..538d5edb0 --- /dev/null +++ b/snippets/migrations/0019_givebanner.py @@ -0,0 +1,33 @@ +# Generated by Django 3.2.9 on 2022-03-14 20:09 + +from django.db import migrations, models +import django.db.models.deletion +import uuid + + +class Migration(migrations.Migration): + + dependencies = [ + ('wagtailimages', '0023_add_choose_permissions'), + ('wagtailcore', '0066_collection_management_permissions'), + ('snippets', '0018_subject_subject_color'), + ] + + operations = [ + migrations.CreateModel( + name='GiveBanner', + fields=[ + ('id', models.AutoField(auto_created=True, primary_key=True, serialize=False, verbose_name='ID')), + ('translation_key', models.UUIDField(default=uuid.uuid4, editable=False)), + ('html_message', models.TextField(default='')), + ('link_text', models.CharField(blank=True, max_length=255, null=True)), + ('link_url', models.URLField(blank=True, null=True)), + ('locale', models.ForeignKey(editable=False, on_delete=django.db.models.deletion.PROTECT, related_name='+', to='wagtailcore.locale')), + ('thumbnail', models.ForeignKey(blank=True, null=True, on_delete=django.db.models.deletion.SET_NULL, related_name='+', to='wagtailimages.image')), + ], + options={ + 'abstract': False, + 'unique_together': {('translation_key', 'locale')}, + }, + ), + ] diff --git a/snippets/models.py b/snippets/models.py index 4f56f844b..9ff0084f0 100644 --- a/snippets/models.py +++ b/snippets/models.py @@ -225,3 +225,37 @@ def __str__(self): register_snippet(SubjectCategory) + +class GiveBanner(TranslatableMixin, models.Model): + html_message = models.TextField(default='') + link_text = models.CharField(max_length=255, null=True, blank=True) + link_url = models.URLField(null=True, blank=True) + thumbnail = models.ForeignKey( + 'wagtailimages.Image', + null=True, + blank=True, + on_delete=models.SET_NULL, + related_name='+' + ) + + def get_banner_thumbnail(self): + return build_image_url(self.thumbnail) + + banner_thumbnail = property(get_banner_thumbnail) + + api_fields = ('html_message', 'link_text', 'link_url', 'banner_thumbnail') + + panels = [ + FieldPanel('html_message'), + FieldPanel('link_text'), + FieldPanel('link_url'), + ImageChooserPanel('thumbnail'), + ] + + def __str__(self): + return 'Give Banner' + + +register_snippet(GiveBanner) + + diff --git a/snippets/serializers.py b/snippets/serializers.py index c030782a0..87956d231 100644 --- a/snippets/serializers.py +++ b/snippets/serializers.py @@ -1,4 +1,4 @@ -from .models import Role, Subject, ErrataContent, SubjectCategory +from .models import Role, Subject, ErrataContent, SubjectCategory, GiveBanner from rest_framework import serializers, generics @@ -39,3 +39,12 @@ class Meta: fields = ('subject_name', 'subject_category', 'description') + + +class GiveBannerSerializer(serializers.ModelSerializer): + class Meta: + model = GiveBanner + fields = ('html_message', + 'link_text', + 'link_url', + 'banner_thumbnail') diff --git a/snippets/tests.py b/snippets/tests.py index f1c80af03..9cadfe5b2 100644 --- a/snippets/tests.py +++ b/snippets/tests.py @@ -6,7 +6,7 @@ from django.conf import settings from django.urls import reverse -from snippets.models import Subject, ErrataContent +from snippets.models import Subject, ErrataContent, GiveBanner class SnippetsTestCase(TestCase): @@ -26,6 +26,9 @@ def setUp(self): self.deprecated = ErrataContent(heading='Errata Content - Deprecated', book_state='deprecated', content='No more corrections will be made') self.deprecated.save() + self.give_banner = GiveBanner(html_message="Help students around the world succeed with contributions of $5, $10 or $20", link_text="Make a difference now", link_url='https://example.com') + self.give_banner.save() + def test_can_create_subject(self): subject = Subject(name="Science", page_content="Science page content.", seo_title="Science SEO Title", search_description="Science page description.") @@ -50,3 +53,7 @@ def test_can_fetch_all_errata_content(self): def test_can_query_errata_content_by_book_state(self): response = self.client.get('/apps/cms/api/snippets/erratacontent/?book_state=deprecated&format=json') self.assertIn(b"deprecated", response.content) + + def test_can_fetch_all_give_banners(self): + response = self.client.get('/apps/cms/api/snippets/givebanner/?format=json') + self.assertIn(b"Help students", response.content) diff --git a/snippets/urls.py b/snippets/urls.py index c84c1f3a1..88ed2ac09 100644 --- a/snippets/urls.py +++ b/snippets/urls.py @@ -6,4 +6,5 @@ router.register(r'subjects', views.SubjectList, basename="Subjects") router.register(r'erratacontent', views.ErrataContentViewSet, basename="ErrataContent") router.register(r'subjectcategory', views.SubjectCategoryViewSet, basename="SubjectCategory") +router.register(r'givebanner', views.GiveBannerViewSet, basename="GiveBanner") urlpatterns = router.urls diff --git a/snippets/views.py b/snippets/views.py index 344c91157..2aa2b1008 100644 --- a/snippets/views.py +++ b/snippets/views.py @@ -1,7 +1,7 @@ from rest_framework import viewsets -from .models import Role, Subject, ErrataContent, SubjectCategory -from .serializers import RoleSerializer, SubjectSerializer, ErrataContentSerializer, SubjectCategorySerializer +from .models import Role, Subject, ErrataContent, SubjectCategory, GiveBanner +from .serializers import RoleSerializer, SubjectSerializer, ErrataContentSerializer, SubjectCategorySerializer, GiveBannerSerializer from rest_framework import generics, viewsets from django_filters.rest_framework import DjangoFilterBackend @@ -61,6 +61,11 @@ def get_queryset(self): return queryset +class GiveBannerViewSet(viewsets.ModelViewSet): + queryset = GiveBanner.objects.all() + serializer_class = GiveBannerSerializer + + def convert_locale(locale): if locale == 'es': return SPANISH_LOCALE_ID From 275ec68ebe2674a618ef63bd6fc0875dda78e61e Mon Sep 17 00:00:00 2001 From: Ed Woodward Date: Tue, 15 Mar 2022 14:03:27 -0500 Subject: [PATCH 2/3] limited Give Banner to one object in view --- snippets/views.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/snippets/views.py b/snippets/views.py index 2aa2b1008..df51719f2 100644 --- a/snippets/views.py +++ b/snippets/views.py @@ -62,7 +62,7 @@ def get_queryset(self): class GiveBannerViewSet(viewsets.ModelViewSet): - queryset = GiveBanner.objects.all() + queryset = GiveBanner.objects.all()[0] serializer_class = GiveBannerSerializer From 24c6dd5bc416f7821152cc2cd6cc56c2a8b0aed8 Mon Sep 17 00:00:00 2001 From: Ed Woodward Date: Tue, 15 Mar 2022 15:11:50 -0500 Subject: [PATCH 3/3] Added validation so only one can be created --- snippets/models.py | 9 +++++++++ snippets/views.py | 3 ++- 2 files changed, 11 insertions(+), 1 deletion(-) diff --git a/snippets/models.py b/snippets/models.py index 9ff0084f0..5e7eb4c88 100644 --- a/snippets/models.py +++ b/snippets/models.py @@ -1,4 +1,5 @@ from django.db import models +from django.core.exceptions import ValidationError from modelcluster.fields import ParentalKey from wagtail.search import index from wagtail.admin.edit_handlers import FieldPanel, InlinePanel @@ -255,6 +256,14 @@ def get_banner_thumbnail(self): def __str__(self): return 'Give Banner' + def clean(self): + if GiveBanner.objects.exists() and not self.pk: + raise ValidationError('There can be only one Give Banner instance') + + def save(self, *args, **kwargs): + self.clean() + return super(GiveBanner, self).save(*args, **kwargs) + register_snippet(GiveBanner) diff --git a/snippets/views.py b/snippets/views.py index df51719f2..2f5d670e5 100644 --- a/snippets/views.py +++ b/snippets/views.py @@ -62,7 +62,8 @@ def get_queryset(self): class GiveBannerViewSet(viewsets.ModelViewSet): - queryset = GiveBanner.objects.all()[0] + # validation prevents multiple Give Banners, so this is safe + queryset = GiveBanner.objects.all() serializer_class = GiveBannerSerializer