We are currently solving the following issue within our repository. Here is the issue text:
--- BEGIN ISSUE ---
Learn's Search is broken
## Summary

* Search within Learn is currently broken on Develop.
* See [triggerSearch()](https://github.com/learningequality/kolibri/blob/develop/kolibri/plugins/learn/assets/src/state/actions.js#L377)

## Exception

`Exception Value: 'list' object has no attribute 'values_list'`

## How to reproduce

1. Search for something within Learn

## Real-life consequences

:rage4: 

--- END ISSUE ---

Below are some code segments, each from a relevant file. One or more of these files may contain bugs.
--- BEGIN FILES ---
Path: `kolibri/content/serializers.py`
Content:
```
1 from django.db.models import Manager
2 from django.db.models.query import RawQuerySet
3 from kolibri.content.models import AssessmentMetaData, ChannelMetadataCache, ContentNode, File
4 from rest_framework import serializers
5 
6 from .content_db_router import default_database_is_attached, get_active_content_database
7 
8 
9 class ChannelMetadataCacheSerializer(serializers.ModelSerializer):
10 
11     class Meta:
12         model = ChannelMetadataCache
13         fields = ('root_pk', 'id', 'name', 'description', 'author')
14 
15 
16 class FileSerializer(serializers.ModelSerializer):
17     storage_url = serializers.SerializerMethodField()
18     preset = serializers.SerializerMethodField()
19     download_url = serializers.SerializerMethodField()
20 
21     def get_storage_url(self, target_node):
22         return target_node.get_storage_url()
23 
24     def get_preset(self, target_node):
25         return target_node.get_preset()
26 
27     def get_download_url(self, target_node):
28         return target_node.get_download_url()
29 
30     class Meta:
31         model = File
32         fields = ('storage_url', 'id', 'priority', 'checksum', 'available', 'file_size', 'extension', 'preset', 'lang',
33                   'supplementary', 'thumbnail', 'download_url')
34 
35 
36 class AssessmentMetaDataSerializer(serializers.ModelSerializer):
37 
38     assessment_item_ids = serializers.JSONField(default='[]')
39     mastery_model = serializers.JSONField(default='{}')
40 
41     class Meta:
42         model = AssessmentMetaData
43         fields = ('assessment_item_ids', 'number_of_assessments', 'mastery_model', 'randomize', 'is_manipulable', )
44 
45 
46 def get_progress_fraction(content_id, user):
47     from kolibri.logger.models import ContentSummaryLog
48     try:
49         # add up all the progress for the logs, and divide by the total number of content nodes to get overall progress
50         overall_progress = ContentSummaryLog.objects.get(user=user, content_id=content_id).progress
51     except ContentSummaryLog.DoesNotExist:
52         return None
53     return round(overall_progress, 4)
54 
55 
56 def get_progress_fractions(nodes, user):
57     from kolibri.logger.models import ContentSummaryLog
58     if isinstance(nodes, RawQuerySet):
59         leaf_ids = [datum.content_id for datum in nodes]
60     else:
61         leaf_ids = nodes.values_list("content_id", flat=True)
62 
63     # get all summary logs for the current user that correspond to the descendant content nodes
64     if default_database_is_attached():  # if possible, do a direct join between the content and default databases
65         channel_alias = get_active_content_database()
66         summary_logs = ContentSummaryLog.objects.using(channel_alias).filter(user=user, content_id__in=leaf_ids)
67     else:  # otherwise, convert the leaf queryset into a flat list of ids and use that
68         summary_logs = ContentSummaryLog.objects.filter(user=user, content_id__in=list(leaf_ids))
69 
70     # make a lookup dict for all logs to allow mapping from content_id to current progress
71     overall_progress = {log['content_id']: round(log['progress'], 4) for log in summary_logs.values('content_id', 'progress')}
72     return overall_progress
73 
74 
75 class ContentNodeListSerializer(serializers.ListSerializer):
76 
77     def to_representation(self, data):
78 
79         if 'request' not in self.context or not self.context['request'].user.is_facility_user:
80             progress_dict = {}
81         else:
82             user = self.context["request"].user
83             progress_dict = get_progress_fractions(data, user)
84 
85         # Dealing with nested relationships, data can be a Manager,
86         # so, first get a queryset from the Manager if needed
87         iterable = data.all() if isinstance(data, Manager) else data
88 
89         return [
90             self.child.to_representation(item, progress_dict.get(item.content_id)) for item in iterable
91         ]
92 
93 
94 class ContentNodeSerializer(serializers.ModelSerializer):
95     parent = serializers.PrimaryKeyRelatedField(read_only=True)
96     files = FileSerializer(many=True, read_only=True)
97     assessmentmetadata = AssessmentMetaDataSerializer(read_only=True, allow_null=True, many=True)
98     license = serializers.StringRelatedField(many=False)
99     license_description = serializers.SerializerMethodField()
100 
101     def __init__(self, *args, **kwargs):
102         # Instantiate the superclass normally
103         super(ContentNodeSerializer, self).__init__(*args, **kwargs)
104 
105         # enable dynamic fields specification!
106         if 'request' in self.context and self.context['request'].GET.get('fields', None):
107             fields = self.context['request'].GET['fields'].split(',')
108             # Drop any fields that are not specified in the `fields` argument.
109             allowed = set(fields)
110             existing = set(self.fields.keys())
111             for field_name in existing - allowed:
112                 self.fields.pop(field_name)
113 
114     def to_representation(self, instance, progress_fraction=None):
115         if progress_fraction is None:
116             if 'request' not in self.context or not self.context['request'].user.is_facility_user:
117                 progress_fraction = 0
118             else:
119                 user = self.context["request"].user
120                 progress_fraction = get_progress_fraction(instance.content_id, user)
121         value = super(ContentNodeSerializer, self).to_representation(instance)
122         value['progress_fraction'] = progress_fraction
123         return value
124 
125     def get_license_description(self, target_node):
126         if target_node.license_id:
127             return target_node.license.license_description
128         return ''
129 
130     class Meta:
131         model = ContentNode
132         fields = (
133             'pk', 'content_id', 'title', 'description', 'kind', 'available', 'sort_order', 'license_owner',
134             'license', 'license_description', 'files', 'parent', 'author',
135             'assessmentmetadata',
136         )
137 
138         list_serializer_class = ContentNodeListSerializer
139
```
--- END FILES ---

Please first localize the bug based on the issue statement, and then generate a patch according to the `git diff` format fenced by three backticks.

Here is an example:

```diff
diff --git a/examples/server_async.py b/examples/server_async.py
--- a/examples/server_async.py
+++ b/examples/server_async.py
@@ -313,4 +313,4 @@
 
 
 if __name__ == "__main__":
-    asyncio.run(run_async_server("."), debug=True)
+    asyncio.run(run_async_server(), debug=True)
diff --git a/examples/server_sync.py b/examples/server_sync.py
--- a/examples/server_sync.py
+++ b/examples/server_sync.py
@@ -313,5 +313,5 @@
 
 
 if __name__ == "__main__":
-    server = run_sync_server(".")
+    server = run_sync_server()
     server.shutdown()

```

diff --git a/kolibri/content/serializers.py b/kolibri/content/serializers.py
--- a/kolibri/content/serializers.py
+++ b/kolibri/content/serializers.py
@@ -55,7 +55,7 @@
 
 def get_progress_fractions(nodes, user):
     from kolibri.logger.models import ContentSummaryLog
-    if isinstance(nodes, RawQuerySet):
+    if isinstance(nodes, RawQuerySet) or isinstance(nodes, list):
         leaf_ids = [datum.content_id for datum in nodes]
     else:
         leaf_ids = nodes.values_list("content_id", flat=True)
@@ -76,6 +76,9 @@
 
     def to_representation(self, data):
 
+        if not data:
+            return data
+
         if 'request' not in self.context or not self.context['request'].user.is_facility_user:
             progress_dict = {}
         else:

{"golden_diff": "diff --git a/kolibri/content/serializers.py b/kolibri/content/serializers.py\n--- a/kolibri/content/serializers.py\n+++ b/kolibri/content/serializers.py\n@@ -55,7 +55,7 @@\n \n def get_progress_fractions(nodes, user):\n     from kolibri.logger.models import ContentSummaryLog\n-    if isinstance(nodes, RawQuerySet):\n+    if isinstance(nodes, RawQuerySet) or isinstance(nodes, list):\n         leaf_ids = [datum.content_id for datum in nodes]\n     else:\n         leaf_ids = nodes.values_list(\"content_id\", flat=True)\n@@ -76,6 +76,9 @@\n \n     def to_representation(self, data):\n \n+        if not data:\n+            return data\n+\n         if 'request' not in self.context or not self.context['request'].user.is_facility_user:\n             progress_dict = {}\n         else:\n", "issue": "Learn's Search is broken\n## Summary\r\n\r\n* Search within Learn is currently broken on Develop.\r\n* See [triggerSearch()](https://github.com/learningequality/kolibri/blob/develop/kolibri/plugins/learn/assets/src/state/actions.js#L377)\r\n\r\n## Exception\r\n\r\n`Exception Value: 'list' object has no attribute 'values_list'`\r\n\r\n## How to reproduce\r\n\r\n1. Search for something within Learn\r\n\r\n## Real-life consequences\r\n\r\n:rage4: \n", "before_files": [{"content": "from django.db.models import Manager\nfrom django.db.models.query import RawQuerySet\nfrom kolibri.content.models import AssessmentMetaData, ChannelMetadataCache, ContentNode, File\nfrom rest_framework import serializers\n\nfrom .content_db_router import default_database_is_attached, get_active_content_database\n\n\nclass ChannelMetadataCacheSerializer(serializers.ModelSerializer):\n\n    class Meta:\n        model = ChannelMetadataCache\n        fields = ('root_pk', 'id', 'name', 'description', 'author')\n\n\nclass FileSerializer(serializers.ModelSerializer):\n    storage_url = serializers.SerializerMethodField()\n    preset = serializers.SerializerMethodField()\n    download_url = serializers.SerializerMethodField()\n\n    def get_storage_url(self, target_node):\n        return target_node.get_storage_url()\n\n    def get_preset(self, target_node):\n        return target_node.get_preset()\n\n    def get_download_url(self, target_node):\n        return target_node.get_download_url()\n\n    class Meta:\n        model = File\n        fields = ('storage_url', 'id', 'priority', 'checksum', 'available', 'file_size', 'extension', 'preset', 'lang',\n                  'supplementary', 'thumbnail', 'download_url')\n\n\nclass AssessmentMetaDataSerializer(serializers.ModelSerializer):\n\n    assessment_item_ids = serializers.JSONField(default='[]')\n    mastery_model = serializers.JSONField(default='{}')\n\n    class Meta:\n        model = AssessmentMetaData\n        fields = ('assessment_item_ids', 'number_of_assessments', 'mastery_model', 'randomize', 'is_manipulable', )\n\n\ndef get_progress_fraction(content_id, user):\n    from kolibri.logger.models import ContentSummaryLog\n    try:\n        # add up all the progress for the logs, and divide by the total number of content nodes to get overall progress\n        overall_progress = ContentSummaryLog.objects.get(user=user, content_id=content_id).progress\n    except ContentSummaryLog.DoesNotExist:\n        return None\n    return round(overall_progress, 4)\n\n\ndef get_progress_fractions(nodes, user):\n    from kolibri.logger.models import ContentSummaryLog\n    if isinstance(nodes, RawQuerySet):\n        leaf_ids = [datum.content_id for datum in nodes]\n    else:\n        leaf_ids = nodes.values_list(\"content_id\", flat=True)\n\n    # get all summary logs for the current user that correspond to the descendant content nodes\n    if default_database_is_attached():  # if possible, do a direct join between the content and default databases\n        channel_alias = get_active_content_database()\n        summary_logs = ContentSummaryLog.objects.using(channel_alias).filter(user=user, content_id__in=leaf_ids)\n    else:  # otherwise, convert the leaf queryset into a flat list of ids and use that\n        summary_logs = ContentSummaryLog.objects.filter(user=user, content_id__in=list(leaf_ids))\n\n    # make a lookup dict for all logs to allow mapping from content_id to current progress\n    overall_progress = {log['content_id']: round(log['progress'], 4) for log in summary_logs.values('content_id', 'progress')}\n    return overall_progress\n\n\nclass ContentNodeListSerializer(serializers.ListSerializer):\n\n    def to_representation(self, data):\n\n        if 'request' not in self.context or not self.context['request'].user.is_facility_user:\n            progress_dict = {}\n        else:\n            user = self.context[\"request\"].user\n            progress_dict = get_progress_fractions(data, user)\n\n        # Dealing with nested relationships, data can be a Manager,\n        # so, first get a queryset from the Manager if needed\n        iterable = data.all() if isinstance(data, Manager) else data\n\n        return [\n            self.child.to_representation(item, progress_dict.get(item.content_id)) for item in iterable\n        ]\n\n\nclass ContentNodeSerializer(serializers.ModelSerializer):\n    parent = serializers.PrimaryKeyRelatedField(read_only=True)\n    files = FileSerializer(many=True, read_only=True)\n    assessmentmetadata = AssessmentMetaDataSerializer(read_only=True, allow_null=True, many=True)\n    license = serializers.StringRelatedField(many=False)\n    license_description = serializers.SerializerMethodField()\n\n    def __init__(self, *args, **kwargs):\n        # Instantiate the superclass normally\n        super(ContentNodeSerializer, self).__init__(*args, **kwargs)\n\n        # enable dynamic fields specification!\n        if 'request' in self.context and self.context['request'].GET.get('fields', None):\n            fields = self.context['request'].GET['fields'].split(',')\n            # Drop any fields that are not specified in the `fields` argument.\n            allowed = set(fields)\n            existing = set(self.fields.keys())\n            for field_name in existing - allowed:\n                self.fields.pop(field_name)\n\n    def to_representation(self, instance, progress_fraction=None):\n        if progress_fraction is None:\n            if 'request' not in self.context or not self.context['request'].user.is_facility_user:\n                progress_fraction = 0\n            else:\n                user = self.context[\"request\"].user\n                progress_fraction = get_progress_fraction(instance.content_id, user)\n        value = super(ContentNodeSerializer, self).to_representation(instance)\n        value['progress_fraction'] = progress_fraction\n        return value\n\n    def get_license_description(self, target_node):\n        if target_node.license_id:\n            return target_node.license.license_description\n        return ''\n\n    class Meta:\n        model = ContentNode\n        fields = (\n            'pk', 'content_id', 'title', 'description', 'kind', 'available', 'sort_order', 'license_owner',\n            'license', 'license_description', 'files', 'parent', 'author',\n            'assessmentmetadata',\n        )\n\n        list_serializer_class = ContentNodeListSerializer\n", "path": "kolibri/content/serializers.py"}], "after_files": [{"content": "from django.db.models import Manager\nfrom django.db.models.query import RawQuerySet\nfrom kolibri.content.models import AssessmentMetaData, ChannelMetadataCache, ContentNode, File\nfrom rest_framework import serializers\n\nfrom .content_db_router import default_database_is_attached, get_active_content_database\n\n\nclass ChannelMetadataCacheSerializer(serializers.ModelSerializer):\n\n    class Meta:\n        model = ChannelMetadataCache\n        fields = ('root_pk', 'id', 'name', 'description', 'author')\n\n\nclass FileSerializer(serializers.ModelSerializer):\n    storage_url = serializers.SerializerMethodField()\n    preset = serializers.SerializerMethodField()\n    download_url = serializers.SerializerMethodField()\n\n    def get_storage_url(self, target_node):\n        return target_node.get_storage_url()\n\n    def get_preset(self, target_node):\n        return target_node.get_preset()\n\n    def get_download_url(self, target_node):\n        return target_node.get_download_url()\n\n    class Meta:\n        model = File\n        fields = ('storage_url', 'id', 'priority', 'checksum', 'available', 'file_size', 'extension', 'preset', 'lang',\n                  'supplementary', 'thumbnail', 'download_url')\n\n\nclass AssessmentMetaDataSerializer(serializers.ModelSerializer):\n\n    assessment_item_ids = serializers.JSONField(default='[]')\n    mastery_model = serializers.JSONField(default='{}')\n\n    class Meta:\n        model = AssessmentMetaData\n        fields = ('assessment_item_ids', 'number_of_assessments', 'mastery_model', 'randomize', 'is_manipulable', )\n\n\ndef get_progress_fraction(content_id, user):\n    from kolibri.logger.models import ContentSummaryLog\n    try:\n        # add up all the progress for the logs, and divide by the total number of content nodes to get overall progress\n        overall_progress = ContentSummaryLog.objects.get(user=user, content_id=content_id).progress\n    except ContentSummaryLog.DoesNotExist:\n        return None\n    return round(overall_progress, 4)\n\n\ndef get_progress_fractions(nodes, user):\n    from kolibri.logger.models import ContentSummaryLog\n    if isinstance(nodes, RawQuerySet) or isinstance(nodes, list):\n        leaf_ids = [datum.content_id for datum in nodes]\n    else:\n        leaf_ids = nodes.values_list(\"content_id\", flat=True)\n\n    # get all summary logs for the current user that correspond to the descendant content nodes\n    if default_database_is_attached():  # if possible, do a direct join between the content and default databases\n        channel_alias = get_active_content_database()\n        summary_logs = ContentSummaryLog.objects.using(channel_alias).filter(user=user, content_id__in=leaf_ids)\n    else:  # otherwise, convert the leaf queryset into a flat list of ids and use that\n        summary_logs = ContentSummaryLog.objects.filter(user=user, content_id__in=list(leaf_ids))\n\n    # make a lookup dict for all logs to allow mapping from content_id to current progress\n    overall_progress = {log['content_id']: round(log['progress'], 4) for log in summary_logs.values('content_id', 'progress')}\n    return overall_progress\n\n\nclass ContentNodeListSerializer(serializers.ListSerializer):\n\n    def to_representation(self, data):\n\n        if not data:\n            return data\n\n        if 'request' not in self.context or not self.context['request'].user.is_facility_user:\n            progress_dict = {}\n        else:\n            user = self.context[\"request\"].user\n            progress_dict = get_progress_fractions(data, user)\n\n        # Dealing with nested relationships, data can be a Manager,\n        # so, first get a queryset from the Manager if needed\n        iterable = data.all() if isinstance(data, Manager) else data\n\n        return [\n            self.child.to_representation(item, progress_dict.get(item.content_id)) for item in iterable\n        ]\n\n\nclass ContentNodeSerializer(serializers.ModelSerializer):\n    parent = serializers.PrimaryKeyRelatedField(read_only=True)\n    files = FileSerializer(many=True, read_only=True)\n    assessmentmetadata = AssessmentMetaDataSerializer(read_only=True, allow_null=True, many=True)\n    license = serializers.StringRelatedField(many=False)\n    license_description = serializers.SerializerMethodField()\n\n    def __init__(self, *args, **kwargs):\n        # Instantiate the superclass normally\n        super(ContentNodeSerializer, self).__init__(*args, **kwargs)\n\n        # enable dynamic fields specification!\n        if 'request' in self.context and self.context['request'].GET.get('fields', None):\n            fields = self.context['request'].GET['fields'].split(',')\n            # Drop any fields that are not specified in the `fields` argument.\n            allowed = set(fields)\n            existing = set(self.fields.keys())\n            for field_name in existing - allowed:\n                self.fields.pop(field_name)\n\n    def to_representation(self, instance, progress_fraction=None):\n        if progress_fraction is None:\n            if 'request' not in self.context or not self.context['request'].user.is_facility_user:\n                progress_fraction = 0\n            else:\n                user = self.context[\"request\"].user\n                progress_fraction = get_progress_fraction(instance.content_id, user)\n        value = super(ContentNodeSerializer, self).to_representation(instance)\n        value['progress_fraction'] = progress_fraction\n        return value\n\n    def get_license_description(self, target_node):\n        if target_node.license_id:\n            return target_node.license.license_description\n        return ''\n\n    class Meta:\n        model = ContentNode\n        fields = (\n            'pk', 'content_id', 'title', 'description', 'kind', 'available', 'sort_order', 'license_owner',\n            'license', 'license_description', 'files', 'parent', 'author',\n            'assessmentmetadata',\n        )\n\n        list_serializer_class = ContentNodeListSerializer\n", "path": "kolibri/content/serializers.py"}]}