We are currently solving the following issue within our repository. Here is the issue text:
--- BEGIN ISSUE ---
recipients column in coach tools in not accurate

### Observed behavior

recipients column always indicates assignment to the entire class, even when that's not true:

![groups](https://user-images.githubusercontent.com/2367265/69926711-644bce80-146a-11ea-8f2b-82ec444fb367.gif)


### Expected behavior

recipients column should be accurate

### User-facing consequences

confusion

### Errors and logs

none observed

### Steps to reproduce

create a lesson and assign it to a group

### Context

0.13.0 beta 3


--- 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/core/lessons/viewsets.py`
Content:
```
1 import json
2 from functools import partial
3 from itertools import chain
4 
5 from django.db import connection
6 from django.db.models import CharField
7 from django_filters.rest_framework import DjangoFilterBackend
8 
9 from .serializers import LessonSerializer
10 from kolibri.core.api import ValuesViewset
11 from kolibri.core.auth.api import KolibriAuthPermissions
12 from kolibri.core.auth.api import KolibriAuthPermissionsFilter
13 from kolibri.core.lessons.models import Lesson
14 from kolibri.core.lessons.models import LessonAssignment
15 from kolibri.core.query import ArrayAgg
16 from kolibri.core.query import GroupConcat
17 from kolibri.core.query import process_uuid_aggregate
18 
19 
20 def _ensure_raw_dict(d):
21     if hasattr(d, "dict"):
22         d = d.dict()
23     return dict(d)
24 
25 
26 class LessonPermissions(KolibriAuthPermissions):
27     # Overrides the default validator to sanitize the Lesson POST Payload
28     # before validation
29     def validator(self, request, view, datum):
30         model = view.get_serializer_class().Meta.model
31         validated_data = view.get_serializer().to_internal_value(
32             _ensure_raw_dict(datum)
33         )
34         # Cannot have create assignments without creating the Lesson first,
35         # so this doesn't try to validate the Lesson with a non-empty lesson_assignments list
36         validated_data.pop("lesson_assignments")
37         return request.user.can_create(model, validated_data)
38 
39 
40 def _map_lesson_classroom(item):
41     return {
42         "id": item.pop("collection__id"),
43         "name": item.pop("collection__name"),
44         "parent": item.pop("collection__parent_id"),
45     }
46 
47 
48 class LessonViewset(ValuesViewset):
49     serializer_class = LessonSerializer
50     filter_backends = (KolibriAuthPermissionsFilter, DjangoFilterBackend)
51     filter_fields = ("collection",)
52     permission_classes = (LessonPermissions,)
53     queryset = Lesson.objects.all().order_by("-date_created")
54 
55     values = (
56         "id",
57         "title",
58         "description",
59         "resources",
60         "is_active",
61         "collection",  # classroom
62         "collection__id",
63         "collection__name",
64         "collection__parent_id",
65         "created_by",
66         "assignment_ids",
67     )
68 
69     field_map = {
70         "classroom": _map_lesson_classroom,
71         "resources": lambda x: json.loads(x["resources"]),
72         "assignment_ids": partial(process_uuid_aggregate, key="assignment_ids"),
73     }
74 
75     def consolidate(self, items):
76         assignment_ids = []
77         for item in items:
78             assignment_ids.extend(item["assignment_ids"])
79         assignments = LessonAssignment.objects.filter(id__in=assignment_ids)
80         if connection.vendor == "postgresql" and ArrayAgg is not None:
81             assignments = assignments.annotate(
82                 learner_ids=ArrayAgg("collection__membership__user__id"),
83             )
84 
85             def _process_item(item):
86                 item["learner_ids"] = map(
87                     lambda x: x.hex, filter(lambda x: x, item["learner_ids"])
88                 )
89                 return item
90 
91         else:
92             assignments = assignments.values("id").annotate(
93                 learner_ids=GroupConcat(
94                     "collection__membership__user__id", output_field=CharField(),
95                 ),
96             )
97 
98             def _process_item(item):
99                 item["learner_ids"] = (
100                     item["learner_ids"].split(",") if item["learner_ids"] else []
101                 )
102                 return item
103 
104         assignments = {
105             a["id"]: _process_item(a)
106             for a in assignments.values(
107                 "id", "collection", "collection__kind", "learner_ids", "assigned_by"
108             )
109         }
110         for item in items:
111             item_ids = item.pop("assignment_ids")
112             item["lesson_assignments"] = [assignments[a] for a in item_ids]
113             item["learner_ids"] = list(
114                 set(
115                     chain.from_iterable(
116                         a.pop("learner_ids") for a in item["lesson_assignments"]
117                     )
118                 )
119             )
120         return items
121 
122     def annotate_queryset(self, queryset):
123         if connection.vendor == "postgresql" and ArrayAgg is not None:
124             return queryset.annotate(assignment_ids=ArrayAgg("lesson_assignments__id"),)
125         return queryset.values("id").annotate(
126             assignment_ids=GroupConcat(
127                 "lesson_assignments__id", output_field=CharField(),
128             ),
129         )
130
```
--- 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/core/lessons/viewsets.py b/kolibri/core/lessons/viewsets.py
--- a/kolibri/core/lessons/viewsets.py
+++ b/kolibri/core/lessons/viewsets.py
@@ -4,6 +4,7 @@
 
 from django.db import connection
 from django.db.models import CharField
+from django.db.models import F
 from django_filters.rest_framework import DjangoFilterBackend
 
 from .serializers import LessonSerializer
@@ -104,7 +105,11 @@
         assignments = {
             a["id"]: _process_item(a)
             for a in assignments.values(
-                "id", "collection", "collection__kind", "learner_ids", "assigned_by"
+                "id",
+                "collection",
+                "learner_ids",
+                "assigned_by",
+                collection_kind=F("collection__kind"),
             )
         }
         for item in items:

{"golden_diff": "diff --git a/kolibri/core/lessons/viewsets.py b/kolibri/core/lessons/viewsets.py\n--- a/kolibri/core/lessons/viewsets.py\n+++ b/kolibri/core/lessons/viewsets.py\n@@ -4,6 +4,7 @@\n \n from django.db import connection\n from django.db.models import CharField\n+from django.db.models import F\n from django_filters.rest_framework import DjangoFilterBackend\n \n from .serializers import LessonSerializer\n@@ -104,7 +105,11 @@\n         assignments = {\n             a[\"id\"]: _process_item(a)\n             for a in assignments.values(\n-                \"id\", \"collection\", \"collection__kind\", \"learner_ids\", \"assigned_by\"\n+                \"id\",\n+                \"collection\",\n+                \"learner_ids\",\n+                \"assigned_by\",\n+                collection_kind=F(\"collection__kind\"),\n             )\n         }\n         for item in items:\n", "issue": "recipients column in coach tools in not accurate\n\r\n### Observed behavior\r\n\r\nrecipients column always indicates assignment to the entire class, even when that's not true:\r\n\r\n![groups](https://user-images.githubusercontent.com/2367265/69926711-644bce80-146a-11ea-8f2b-82ec444fb367.gif)\r\n\r\n\r\n### Expected behavior\r\n\r\nrecipients column should be accurate\r\n\r\n### User-facing consequences\r\n\r\nconfusion\r\n\r\n### Errors and logs\r\n\r\nnone observed\r\n\r\n### Steps to reproduce\r\n\r\ncreate a lesson and assign it to a group\r\n\r\n### Context\r\n\r\n0.13.0 beta 3\r\n\n", "before_files": [{"content": "import json\nfrom functools import partial\nfrom itertools import chain\n\nfrom django.db import connection\nfrom django.db.models import CharField\nfrom django_filters.rest_framework import DjangoFilterBackend\n\nfrom .serializers import LessonSerializer\nfrom kolibri.core.api import ValuesViewset\nfrom kolibri.core.auth.api import KolibriAuthPermissions\nfrom kolibri.core.auth.api import KolibriAuthPermissionsFilter\nfrom kolibri.core.lessons.models import Lesson\nfrom kolibri.core.lessons.models import LessonAssignment\nfrom kolibri.core.query import ArrayAgg\nfrom kolibri.core.query import GroupConcat\nfrom kolibri.core.query import process_uuid_aggregate\n\n\ndef _ensure_raw_dict(d):\n    if hasattr(d, \"dict\"):\n        d = d.dict()\n    return dict(d)\n\n\nclass LessonPermissions(KolibriAuthPermissions):\n    # Overrides the default validator to sanitize the Lesson POST Payload\n    # before validation\n    def validator(self, request, view, datum):\n        model = view.get_serializer_class().Meta.model\n        validated_data = view.get_serializer().to_internal_value(\n            _ensure_raw_dict(datum)\n        )\n        # Cannot have create assignments without creating the Lesson first,\n        # so this doesn't try to validate the Lesson with a non-empty lesson_assignments list\n        validated_data.pop(\"lesson_assignments\")\n        return request.user.can_create(model, validated_data)\n\n\ndef _map_lesson_classroom(item):\n    return {\n        \"id\": item.pop(\"collection__id\"),\n        \"name\": item.pop(\"collection__name\"),\n        \"parent\": item.pop(\"collection__parent_id\"),\n    }\n\n\nclass LessonViewset(ValuesViewset):\n    serializer_class = LessonSerializer\n    filter_backends = (KolibriAuthPermissionsFilter, DjangoFilterBackend)\n    filter_fields = (\"collection\",)\n    permission_classes = (LessonPermissions,)\n    queryset = Lesson.objects.all().order_by(\"-date_created\")\n\n    values = (\n        \"id\",\n        \"title\",\n        \"description\",\n        \"resources\",\n        \"is_active\",\n        \"collection\",  # classroom\n        \"collection__id\",\n        \"collection__name\",\n        \"collection__parent_id\",\n        \"created_by\",\n        \"assignment_ids\",\n    )\n\n    field_map = {\n        \"classroom\": _map_lesson_classroom,\n        \"resources\": lambda x: json.loads(x[\"resources\"]),\n        \"assignment_ids\": partial(process_uuid_aggregate, key=\"assignment_ids\"),\n    }\n\n    def consolidate(self, items):\n        assignment_ids = []\n        for item in items:\n            assignment_ids.extend(item[\"assignment_ids\"])\n        assignments = LessonAssignment.objects.filter(id__in=assignment_ids)\n        if connection.vendor == \"postgresql\" and ArrayAgg is not None:\n            assignments = assignments.annotate(\n                learner_ids=ArrayAgg(\"collection__membership__user__id\"),\n            )\n\n            def _process_item(item):\n                item[\"learner_ids\"] = map(\n                    lambda x: x.hex, filter(lambda x: x, item[\"learner_ids\"])\n                )\n                return item\n\n        else:\n            assignments = assignments.values(\"id\").annotate(\n                learner_ids=GroupConcat(\n                    \"collection__membership__user__id\", output_field=CharField(),\n                ),\n            )\n\n            def _process_item(item):\n                item[\"learner_ids\"] = (\n                    item[\"learner_ids\"].split(\",\") if item[\"learner_ids\"] else []\n                )\n                return item\n\n        assignments = {\n            a[\"id\"]: _process_item(a)\n            for a in assignments.values(\n                \"id\", \"collection\", \"collection__kind\", \"learner_ids\", \"assigned_by\"\n            )\n        }\n        for item in items:\n            item_ids = item.pop(\"assignment_ids\")\n            item[\"lesson_assignments\"] = [assignments[a] for a in item_ids]\n            item[\"learner_ids\"] = list(\n                set(\n                    chain.from_iterable(\n                        a.pop(\"learner_ids\") for a in item[\"lesson_assignments\"]\n                    )\n                )\n            )\n        return items\n\n    def annotate_queryset(self, queryset):\n        if connection.vendor == \"postgresql\" and ArrayAgg is not None:\n            return queryset.annotate(assignment_ids=ArrayAgg(\"lesson_assignments__id\"),)\n        return queryset.values(\"id\").annotate(\n            assignment_ids=GroupConcat(\n                \"lesson_assignments__id\", output_field=CharField(),\n            ),\n        )\n", "path": "kolibri/core/lessons/viewsets.py"}], "after_files": [{"content": "import json\nfrom functools import partial\nfrom itertools import chain\n\nfrom django.db import connection\nfrom django.db.models import CharField\nfrom django.db.models import F\nfrom django_filters.rest_framework import DjangoFilterBackend\n\nfrom .serializers import LessonSerializer\nfrom kolibri.core.api import ValuesViewset\nfrom kolibri.core.auth.api import KolibriAuthPermissions\nfrom kolibri.core.auth.api import KolibriAuthPermissionsFilter\nfrom kolibri.core.lessons.models import Lesson\nfrom kolibri.core.lessons.models import LessonAssignment\nfrom kolibri.core.query import ArrayAgg\nfrom kolibri.core.query import GroupConcat\nfrom kolibri.core.query import process_uuid_aggregate\n\n\ndef _ensure_raw_dict(d):\n    if hasattr(d, \"dict\"):\n        d = d.dict()\n    return dict(d)\n\n\nclass LessonPermissions(KolibriAuthPermissions):\n    # Overrides the default validator to sanitize the Lesson POST Payload\n    # before validation\n    def validator(self, request, view, datum):\n        model = view.get_serializer_class().Meta.model\n        validated_data = view.get_serializer().to_internal_value(\n            _ensure_raw_dict(datum)\n        )\n        # Cannot have create assignments without creating the Lesson first,\n        # so this doesn't try to validate the Lesson with a non-empty lesson_assignments list\n        validated_data.pop(\"lesson_assignments\")\n        return request.user.can_create(model, validated_data)\n\n\ndef _map_lesson_classroom(item):\n    return {\n        \"id\": item.pop(\"collection__id\"),\n        \"name\": item.pop(\"collection__name\"),\n        \"parent\": item.pop(\"collection__parent_id\"),\n    }\n\n\nclass LessonViewset(ValuesViewset):\n    serializer_class = LessonSerializer\n    filter_backends = (KolibriAuthPermissionsFilter, DjangoFilterBackend)\n    filter_fields = (\"collection\",)\n    permission_classes = (LessonPermissions,)\n    queryset = Lesson.objects.all().order_by(\"-date_created\")\n\n    values = (\n        \"id\",\n        \"title\",\n        \"description\",\n        \"resources\",\n        \"is_active\",\n        \"collection\",  # classroom\n        \"collection__id\",\n        \"collection__name\",\n        \"collection__parent_id\",\n        \"created_by\",\n        \"assignment_ids\",\n    )\n\n    field_map = {\n        \"classroom\": _map_lesson_classroom,\n        \"resources\": lambda x: json.loads(x[\"resources\"]),\n        \"assignment_ids\": partial(process_uuid_aggregate, key=\"assignment_ids\"),\n    }\n\n    def consolidate(self, items):\n        assignment_ids = []\n        for item in items:\n            assignment_ids.extend(item[\"assignment_ids\"])\n        assignments = LessonAssignment.objects.filter(id__in=assignment_ids)\n        if connection.vendor == \"postgresql\" and ArrayAgg is not None:\n            assignments = assignments.annotate(\n                learner_ids=ArrayAgg(\"collection__membership__user__id\"),\n            )\n\n            def _process_item(item):\n                item[\"learner_ids\"] = map(\n                    lambda x: x.hex, filter(lambda x: x, item[\"learner_ids\"])\n                )\n                return item\n\n        else:\n            assignments = assignments.values(\"id\").annotate(\n                learner_ids=GroupConcat(\n                    \"collection__membership__user__id\", output_field=CharField(),\n                ),\n            )\n\n            def _process_item(item):\n                item[\"learner_ids\"] = (\n                    item[\"learner_ids\"].split(\",\") if item[\"learner_ids\"] else []\n                )\n                return item\n\n        assignments = {\n            a[\"id\"]: _process_item(a)\n            for a in assignments.values(\n                \"id\",\n                \"collection\",\n                \"learner_ids\",\n                \"assigned_by\",\n                collection_kind=F(\"collection__kind\"),\n            )\n        }\n        for item in items:\n            item_ids = item.pop(\"assignment_ids\")\n            item[\"lesson_assignments\"] = [assignments[a] for a in item_ids]\n            item[\"learner_ids\"] = list(\n                set(\n                    chain.from_iterable(\n                        a.pop(\"learner_ids\") for a in item[\"lesson_assignments\"]\n                    )\n                )\n            )\n        return items\n\n    def annotate_queryset(self, queryset):\n        if connection.vendor == \"postgresql\" and ArrayAgg is not None:\n            return queryset.annotate(assignment_ids=ArrayAgg(\"lesson_assignments__id\"),)\n        return queryset.values(\"id\").annotate(\n            assignment_ids=GroupConcat(\n                \"lesson_assignments__id\", output_field=CharField(),\n            ),\n        )\n", "path": "kolibri/core/lessons/viewsets.py"}]}