def _run_test(serializer_cls, model_cls, sql_queries=1, *, excluded_fields=None, extra_select_fields=None, extra_prefetch_fields=None, ) -> ReturnList: """ Boilerplate for running the tests :return: the serializer data to assert one """ print( f'Running test with serializer "{serializer_cls.__name__}" and model {model_cls.__name__}' ) case = TestCase() request = APIRequestFactory().get("/FOO") with case.assertNumQueries(sql_queries): print(excluded_fields, extra_select_fields, extra_prefetch_fields) prefetched_queryset = prefetch(model_cls.objects.all(), serializer_cls, excluded_fields=excluded_fields, extra_select_fields=extra_select_fields, extra_prefetch_fields=extra_prefetch_fields) serializer_instance = serializer_cls( instance=prefetched_queryset, many=True, context={"request": request} ) print("Data returned:") pprint_result(serializer_instance.data) return serializer_instance.data
def get_queryset(self): """ Annotate the number of questions asked, number of questioned currently being answered, and the number of active staff members. Filter/annotation pattern taken from here: https://stackoverflow.com/questions/42543978/django-1-11-annotating-a-subquery-aggregate """ questions = (Question.objects.filter( queue=OuterRef("pk")).order_by().values("queue").annotate( count=Count("*")).values("count")) questions_active = questions.filter(status=Question.STATUS_ACTIVE) questions_asked = questions.filter(status=Question.STATUS_ASKED) time_threshold = timezone.now() - timedelta(minutes=1) staff_active = (Membership.objects.filter( Q(course=OuterRef("course__pk")) & ~Q(kind=Membership.KIND_STUDENT) & Q(last_active__gt=time_threshold)).order_by().values( "course").annotate(count=Count( "*", output_field=FloatField()), ).values("count")) qs = (Queue.objects.filter( course=self.kwargs["course_pk"], archived=False).annotate( questions_active=Subquery(questions_active[:1], output_field=IntegerField()), questions_asked=Subquery(questions_asked[:1]), staff_active=Subquery(staff_active[:1]), ).order_by("id")) return prefetch(qs, self.serializer_class)
def get_queryset(self): position = (Question.objects.filter( Q(queue=OuterRef("queue")) & Q(status=Question.STATUS_ASKED) & Q(time_asked__lte=OuterRef("time_asked")) ).values("queue").annotate( count=Count("queue", output_field=IntegerField())).values("count")) qs = (Question.objects.filter( Q(queue=self.kwargs["queue_pk"]) & (Q(status=Question.STATUS_ASKED) | Q(status=Question.STATUS_ACTIVE))).annotate(position=Case( When( status=Question.STATUS_ASKED, then=Subquery(position[:1]), ), default=-1, )).order_by("time_asked")) membership = Membership.objects.get(course=self.kwargs["course_pk"], user=self.request.user) if not membership.is_ta: qs = qs.filter(asked_by=self.request.user) return prefetch(qs, self.serializer_class)
def get_queryset(self): is_member = Membership.objects.filter(course=OuterRef("pk"), user=self.request.user) qs = (Course.objects.filter( Q(invite_only=False) | Q(membership__user=self.request.user)).distinct().annotate( is_member=Exists(is_member))) return prefetch(qs, self.get_serializer_class())
def test_it_prefetches_foreign_key_relations_when_owning(self): serializer_class = ChildBSerializer queryset = ChildB.objects.all() queryset = prefetch(queryset, serializer_class) serializer = serializer_class(instance=queryset, many=True) with self.assertNumQueries(1): print(serializer.data)
def test_it_prefetches_slug_related_fields(self): serializer_class = ChildBSerializerWithSlug queryset = ChildB.objects.all() queryset = prefetch(queryset, serializer_class) with self.assertNumQueries(1): serializer = ChildBSerializerWithSlug(instance=queryset, many=True) assert serializer.data[0]["parent"] == "foo" print(serializer.data)
def test_reverse_foreign_key_lookups(self): serializer_class = ChildBSerializerWithDottedPropertyAccess queryset = ChildB.objects.all() with self.assertNumQueries(1): queryset = prefetch(queryset, serializer_class) serializer = serializer_class(instance=queryset, many=True) data = serializer.data print(data) assert len(data) == 1 assert data[0]["parent_text"] == "foo"
def test_it_prefetches_when_using_dotted_property_access(self): serializer_class = ChildBSerializerWithDottedPropertyAccess queryset = ChildB.objects.all() with self.assertNumQueries(1): queryset = prefetch(queryset, serializer_class) serializer = serializer_class(instance=queryset, many=True) data = serializer.data print(data) assert len(data) == 1 assert data[0]["parent_text"] == "foo"
def test_it_prefetches_using_nested_serializers_when_source_is_changed(self): serializer_class = ChildBSerializerWithNestedRenamedSerializer queryset = ChildB.objects.all() queryset = prefetch(queryset, serializer_class) serializer = serializer_class(instance=queryset, many=True) with self.assertNumQueries(1): data = serializer.data print(data) assert len(data) == 1 assert data[0]["dad"]["top_level_text"] == "foo"
def get_queryset(self): qs = Membership.objects.filter( course=self.kwargs["course_pk"]).order_by("user__first_name") membership = Membership.objects.get(course=self.kwargs["course_pk"], user=self.request.user) if not membership.is_ta: qs = qs.filter( Q(kind=Membership.KIND_PROFESSOR) | Q(kind=Membership.KIND_HEAD_TA) | Q(user=self.request.user)) return prefetch(qs, self.serializer_class)
def _run_test(serializer_cls, model_cls, sql_queries=1) -> ReturnList: """ Boilerplate for running the tests :return: the serializer data to assert one """ print( f'Running test with serializer "{serializer_cls.__name__}" and model {model_cls.__name__}' ) case = TestCase() with case.assertNumQueries(sql_queries): prefetched_queryset = prefetch(model_cls.objects.all(), serializer_cls) serializer_instance = serializer_cls(instance=prefetched_queryset, many=True) print("Data returned:") pprint_result(serializer_instance.data) return serializer_instance.data
def get_queryset(self): # Simply do the extra select_related / prefetch_related here # and leave the mixin to do the rest of the work queryset = Product.objects.all() queryset = queryset.select_related() return django_auto_prefetching.prefetch(queryset, self.serializer_class)
def get_queryset(self): # might need to change qs if students shouldn't be able to see all queue statistics qs = QueueStatistic.objects.filter(queue=self.kwargs["queue_pk"]) return prefetch(qs, self.serializer_class)
def get_queryset(self): qs = CourseStatistic.objects.filter(course=self.kwargs["course_pk"]) return prefetch(qs, self.serializer_class)
def get_queryset(self): qs = Question.objects.filter(queue__in=Queue.objects.filter( course=self.kwargs["course_pk"])).order_by("time_asked") return prefetch(qs, self.serializer_class)