Skip to content

Commit

Permalink
Collection, subject and category are not required on blog posts, adde…
Browse files Browse the repository at this point in the history
…d webinar search by subject (#1307)

* Collection, subject and category are not required on blog posts, added webinar search by subject

* removed unneeded code

* Fixed Webinar API for search and all webinars

* Fixed test

* Added test for all webinars

* Removed commented out code
  • Loading branch information
edwoodward authored Jun 28, 2022
1 parent 89af955 commit 30ef3bb
Show file tree
Hide file tree
Showing 10 changed files with 209 additions and 18 deletions.
31 changes: 31 additions & 0 deletions news/migrations/0046_auto_20220616_1349.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,31 @@
# Generated by Django 3.2.5 on 2022-06-16 18:49

from django.db import migrations
import news.models
import wagtail.core.blocks
import wagtail.core.fields


class Migration(migrations.Migration):

dependencies = [
('news', '0045_merge_20220520_1523'),
]

operations = [
migrations.AlterField(
model_name='newsarticle',
name='article_subjects',
field=wagtail.core.fields.StreamField([('subject', wagtail.core.blocks.ListBlock(wagtail.core.blocks.StructBlock([('subject', news.models.BlogCollectionChooserBlock(label='Blog Subject', required=True, target_model='snippets.Subject')), ('featured', wagtail.core.blocks.BooleanBlock(label='Featured', required=False))])))], blank=True, null=True),
),
migrations.AlterField(
model_name='newsarticle',
name='collections',
field=wagtail.core.fields.StreamField([('collection', wagtail.core.blocks.ListBlock(wagtail.core.blocks.StructBlock([('collection', news.models.BlogCollectionChooserBlock(label='Blog Collection', required=True, target_model='snippets.BlogCollection')), ('featured', wagtail.core.blocks.BooleanBlock(label='Featured', required=False)), ('popular', wagtail.core.blocks.BooleanBlock(label='Popular', required=False))])))], blank=True, null=True),
),
migrations.AlterField(
model_name='newsarticle',
name='content_types',
field=wagtail.core.fields.StreamField([('content_type', wagtail.core.blocks.ListBlock(wagtail.core.blocks.StructBlock([('content_type', news.models.ContentTypeChooserBlock(label='Blog Content Type', required=True, target_model='snippets.BlogContentType'))])))], blank=True, null=True),
),
]
7 changes: 4 additions & 3 deletions news/models.py
Original file line number Diff line number Diff line change
Expand Up @@ -127,6 +127,7 @@ def get_api_representation(self, value, context=None):

class SubjectBlock(StructBlock):
subject = BlogCollectionChooserBlock(required=True, label='Blog Subject', target_model='snippets.Subject')
featured = BooleanBlock(label="Featured", required=False)


class BlogCollectionBlock(StructBlock):
Expand Down Expand Up @@ -273,13 +274,13 @@ def get_article_image(self):
gated_content = models.BooleanField(default=False)
collections = StreamField(blocks.StreamBlock([
('collection', blocks.ListBlock(BlogCollectionBlock())
)]), null=True)
)]), null=True, blank=True)
article_subjects = StreamField(blocks.StreamBlock([
('subject', blocks.ListBlock(SubjectBlock())
)]), null=True)
)]), null=True, blank=True)
content_types = StreamField(blocks.StreamBlock([
('content_type', blocks.ListBlock(BlogContentTypeBlock())
)]), null=True)
)]), null=True, blank=True)
promote_image = models.ForeignKey(
'wagtailimages.Image',
null=True,
Expand Down
4 changes: 2 additions & 2 deletions openstax/settings/local.py.example
Original file line number Diff line number Diff line change
@@ -1,9 +1,9 @@
from .base import INSTALLED_APPS, MIDDLEWARE_CLASSES
from .base import INSTALLED_APPS, MIDDLEWARE
INSTALLED_APPS += (
'debug_toolbar',
'django_extensions',
)
MIDDLEWARE_CLASSES += (
MIDDLEWARE += (
'debug_toolbar.middleware.DebugToolbarMiddleware',
)
# django-debug-toolbar settings
Expand Down
2 changes: 1 addition & 1 deletion openstax/urls.py
Original file line number Diff line number Diff line change
Expand Up @@ -47,7 +47,7 @@
path('errata/', include('errata.urls')),
path('apps/cms/api/errata/', include('errata.urls')),
path('apps/cms/api/events/', include('events.urls')),
path('apps/cms/api/', include('webinars.urls')),
path('apps/cms/api/webinars/', include('webinars.urls')),
path('apps/cms/api/donations/', include('donations.urls')),

# route everything to /api/spike also...
Expand Down
21 changes: 21 additions & 0 deletions webinars/migrations/0003_webinar_webinar_subjects.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,21 @@
# Generated by Django 3.2.5 on 2022-06-16 18:58

from django.db import migrations
import news.models
import wagtail.core.blocks
import wagtail.core.fields


class Migration(migrations.Migration):

dependencies = [
('webinars', '0002_webinar_display_on_tutor_page'),
]

operations = [
migrations.AddField(
model_name='webinar',
name='webinar_subjects',
field=wagtail.core.fields.StreamField([('subject', wagtail.core.blocks.ListBlock(wagtail.core.blocks.StructBlock([('subject', news.models.BlogCollectionChooserBlock(label='Blog Subject', required=True, target_model='snippets.Subject')), ('featured', wagtail.core.blocks.BooleanBlock(label='Featured', required=False))])))], blank=True, null=True),
),
]
43 changes: 43 additions & 0 deletions webinars/models.py
Original file line number Diff line number Diff line change
@@ -1,4 +1,22 @@
import json

from django.db import models
from wagtail.core import blocks
from wagtail.core.fields import StreamField
from news.models import SubjectBlock
from snippets.models import Subject


def webinar_subject_search(subject):
webinars = Webinar.objects.all()
webinars_to_return = []
for webinar in webinars:
webinar_subjects = webinar.selected_subjects
if subject in webinar_subjects:
webinars_to_return.append(webinar)

return webinars_to_return


class Webinar(models.Model):
start = models.DateTimeField()
Expand All @@ -10,6 +28,31 @@ class Webinar(models.Model):
registration_url = models.URLField()
registration_link_text = models.CharField(max_length=255)
display_on_tutor_page = models.BooleanField(default=False)
webinar_subjects = StreamField(blocks.StreamBlock([
('subject', blocks.ListBlock(SubjectBlock())
)]), null=True, blank=True)

@property
def selected_subjects(self):
prep_value = self.webinar_subjects.get_prep_value()
subjects = []
for s in prep_value:
for x in s['value']:
subject_id = x['value']['subject']
subject = Subject.objects.filter(id=subject_id)
subjects.append(str(subject[0]))
return subjects

def selected_subjects_json(self):
prep_value = self.webinar_subjects.get_prep_value()
subjects = []
for s in prep_value:
for x in s['value']:
subject_id = x['value']['subject']
featured = x['value']['featured']
subject = Subject.objects.filter(id=subject_id)
subjects.append({"subject":str(subject[0]), "featured":str(featured)})
return subjects

def __str__(self):
return self.title
29 changes: 24 additions & 5 deletions webinars/serializers.py
Original file line number Diff line number Diff line change
@@ -1,13 +1,32 @@
from rest_framework import serializers
from .models import Webinar


class WebinarSerializer(serializers.ModelSerializer):
def __init__(self, *args, **kwargs):
super(WebinarSerializer, self).__init__(*args, **kwargs)
subjects = serializers.SerializerMethodField()

for field in self.fields:
self.fields[field].read_only = True
def get_subjects(self, obj):
return obj.selected_subjects_json()

class Meta:
model = Webinar
fields = '__all__'
fields = ('id',
'start',
'end',
'description',
'speakers',
'spaces_remaining',
'registration_url',
'registration_link_text',
'display_on_tutor_page',
'subjects')
read_only_fields = ('id',
'start',
'end',
'description',
'speakers',
'spaces_remaining',
'registration_url',
'registration_link_text',
'display_on_tutor_page',
'subjects')
74 changes: 74 additions & 0 deletions webinars/tests.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,74 @@
import json

from django.test import TestCase
from django.utils import timezone
from wagtail.tests.utils import WagtailPageTests

from snippets.models import Subject
from webinars.models import Webinar


class WebinarTests(WagtailPageTests, TestCase):
def setUp(self):
# create subjects
self.math = Subject(name="Math", page_content="Math page content.", seo_title="Math SEO Title",
search_description="Math page description.")
self.math.save()
math_id = self.math.id

self.economics = Subject(name="Economics", page_content="Economics page content.",
seo_title="Economics SEO Title",
search_description="Economics page description.")
self.economics.save()
economics_id = self.economics.id

# create webinars
self.webinar = Webinar(title="Webinar 1",
start=timezone.now(),
end=timezone.now(),
description='Webinar 1 description',
speakers='Bob, Mary. Sally, Mike',
spaces_remaining=45,
registration_url='https://example.com',
registration_link_text='Register Now',
display_on_tutor_page=False,
webinar_subjects=json.dumps(
[

{"type": "subject", "value": [
{"type": "item", "value": {"subject": math_id, "featured": False},
"id": "fb443e9a-5487-4b5e-86f3-69017c0327b5"}]
}
]
),
)
self.webinar.save()
self.webinar2 = Webinar(title="Webinar 2",
start=timezone.now(),
end=timezone.now(),
description='Webinar 2 description',
speakers='Stan, Steve, Tony',
spaces_remaining=54,
registration_url='https://example.com',
registration_link_text='Register Now',
display_on_tutor_page=False,
webinar_subjects=json.dumps(
[

{"type": "subject", "value": [
{"type": "item", "value": {"subject": economics_id, "featured": False},
"id": "fb443e9a-5487-4b5e-86f3-69017c0327b5"}]
}
]
),
)
self.webinar2.save()

def test_search_subject_only(self):
response = self.client.get('/apps/cms/api/webinars/?subject=Math')
self.assertContains(response, 'Math')

def test_all_webinars(self):
response = self.client.get('/apps/cms/api/webinars/')
self.assertContains(response, 'Math')
self.assertContains(response, 'Economics')
2 changes: 1 addition & 1 deletion webinars/urls.py
Original file line number Diff line number Diff line change
Expand Up @@ -3,7 +3,7 @@
from . import views

router = routers.SimpleRouter()
router.register(r'webinars', views.WebinarViewSet, basename='Webinars')
router.register(r'', views.WebinarViewSet, basename='Webinars')

urlpatterns = [
path(r'', include(router.urls)),
Expand Down
14 changes: 8 additions & 6 deletions webinars/views.py
Original file line number Diff line number Diff line change
@@ -1,13 +1,15 @@
from rest_framework import viewsets

from django.shortcuts import render
from django.http import JsonResponse
from django.conf import settings

from .models import Webinar
from .models import Webinar, webinar_subject_search
from .serializers import WebinarSerializer


class WebinarViewSet(viewsets.ModelViewSet):
queryset = Webinar.objects.all()
serializer_class = WebinarSerializer

def get_queryset(self):
queryset = Webinar.objects.all()
subject = self.request.query_params.get('subject', None)
if subject is not None:
queryset = webinar_subject_search(subject)
return queryset

0 comments on commit 30ef3bb

Please sign in to comment.