Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
9 changes: 6 additions & 3 deletions learning_resources/filters_test.py
Original file line number Diff line number Diff line change
Expand Up @@ -448,15 +448,18 @@ def test_learning_resource_filter_course_features(client):
"""Test that the resource_content_tag filter works"""

resource_with_exams = LearningResourceFactory.create(
content_tags=LearningResourceContentTagFactory.create_batch(1, name="Exams")
content_tags=LearningResourceContentTagFactory.create_batch(1, name="Exams"),
resource_type=LearningResourceType.video.name,
)
resource_with_notes = LearningResourceFactory.create(
content_tags=LearningResourceContentTagFactory.create_batch(
1, name="Lecture Notes"
)
),
resource_type=LearningResourceType.video.name,
)
LearningResourceFactory.create(
content_tags=LearningResourceContentTagFactory.create_batch(1, name="Other")
content_tags=LearningResourceContentTagFactory.create_batch(1, name="Other"),
resource_type=LearningResourceType.video.name,
)

results = client.get(f"{RESOURCE_API_URL}?course_feature=exams").json()["results"]
Expand Down
18 changes: 18 additions & 0 deletions learning_resources/models.py
Original file line number Diff line number Diff line change
Expand Up @@ -390,6 +390,13 @@ def for_serialization(self, *, user: Optional["User"] = None):
),
to_attr="_podcasts",
),
Prefetch(
"parents",
queryset=LearningResourceRelationship.objects.filter(
relation_type=LearningResourceRelationTypes.PLAYLIST_VIDEOS.value,
),
to_attr="_playlists",
),
Prefetch(
"children",
queryset=LearningResourceRelationship.objects.select_related(
Expand Down Expand Up @@ -604,6 +611,17 @@ def podcasts(self) -> list["LearningResourceRelationship"]:
),
)

@cached_property
def playlists(self) -> list["LearningResourceRelationship"]:
"""Return a list of playlists that the resource is in"""
return getattr(
self,
"_playlists",
self.parents.filter(
relation_type=LearningResourceRelationTypes.PLAYLIST_VIDEOS.value,
),
)

class Meta:
unique_together = (("platform", "readable_id", "resource_type"),)

Expand Down
6 changes: 1 addition & 5 deletions learning_resources/serializers.py
Original file line number Diff line number Diff line change
Expand Up @@ -1097,11 +1097,7 @@ class VideoResourceSerializer(LearningResourceBaseSerializer):

def get_playlists(self, instance) -> list[str]:
"""Get the playlist id(s) the video belongs to"""
return list(
instance.parents.filter(
relation_type=constants.LearningResourceRelationTypes.PLAYLIST_VIDEOS.value
).values_list("parent__id", flat=True)
)
return [playlist.parent_id for playlist in instance.playlists]


class VideoPlaylistResourceSerializer(LearningResourceBaseSerializer):
Expand Down
36 changes: 35 additions & 1 deletion learning_resources/serializers_test.py
Original file line number Diff line number Diff line change
Expand Up @@ -33,7 +33,11 @@
LearningResourcePriceFactory,
LearningResourceRunFactory,
)
from learning_resources.models import ContentFile, LearningResource
from learning_resources.models import (
ContentFile,
LearningResource,
LearningResourceRelationship,
)
from main.test_utils import assert_json_equal, drf_datetime
from main.utils import frontend_absolute_url

Expand Down Expand Up @@ -141,6 +145,36 @@ def test_serialize_podcast_episode_to_json():
)


def test_serialize_video_resource_playlists_to_json():
"""
Verify that a serialized video resource has the correct playlist data
"""
playlist = factories.VideoPlaylistFactory.create()
video = factories.VideoFactory.create()
LearningResourceRelationship.objects.get_or_create(
parent=playlist.learning_resource,
child=video.learning_resource,
relation_type=LearningResourceRelationTypes.PLAYLIST_VIDEOS.value,
)
serializer = serializers.VideoResourceSerializer(instance=video.learning_resource)
assert serializer.data["playlists"] == [playlist.learning_resource.id]


def test_serialize_podcast_episode_playlists_to_json():
"""
Verify that a serialized podcast episode resource has the correct podcast data
"""
podcast = factories.PodcastFactory.create()
podcast_episode = factories.PodcastEpisodeFactory.create()
LearningResourceRelationship.objects.get_or_create(
parent=podcast.learning_resource,
child=podcast_episode.learning_resource,
relation_type=LearningResourceRelationTypes.PODCAST_EPISODES.value,
)
serializer = serializers.PodcastEpisodeSerializer(instance=podcast_episode)
assert serializer.data["podcasts"] == [podcast.learning_resource.id]


@pytest.mark.parametrize("has_context", [True, False])
@pytest.mark.parametrize(
("params", "detail_key", "specific_serializer_cls", "detail_serializer_cls"),
Expand Down
4 changes: 2 additions & 2 deletions learning_resources/views_test.py
Original file line number Diff line number Diff line change
Expand Up @@ -194,7 +194,7 @@ def test_program_detail_endpoint(client, django_assert_num_queries, url):
"""Test program endpoint"""
program = ProgramFactory.create()
assert program.learning_resource.children.count() > 0
with django_assert_num_queries(20): # should be same # regardless of child count
with django_assert_num_queries(21): # should be same # regardless of child count
resp = client.get(reverse(url, args=[program.learning_resource.id]))
assert resp.data.get("title") == program.learning_resource.title
assert resp.data.get("resource_type") == LearningResourceType.program.name
Expand Down Expand Up @@ -239,7 +239,7 @@ def test_no_excess_queries(rf, user, mocker, django_assert_num_queries, course_c
request = rf.get("/")
request.user = user

with django_assert_num_queries(22):
with django_assert_num_queries(23):
view = CourseViewSet(request=request)
results = view.get_queryset().all()
assert len(results) == course_count
Expand Down
Loading