<commit_before>import datetime
from itertools import accumulate

from django.db.models import Count, Sum, Case, F, When, Value, IntegerField, Min
from rest_framework import viewsets
from rest_framework.decorators import list_route
from rest_framework.filters import DjangoFilterBackend
from rest_framework.generics import ListAPIView
from rest_framework.metadata import SimpleMetadata
from rest_framework.pagination import PageNumberPagination
from rest_framework.permissions import (
    IsAuthenticatedOrReadOnly, IsAuthenticated, BasePermission
)
from rest_framework.renderers import BrowsableAPIRenderer, JSONRenderer
from rest_framework.response import Response
from rest_framework.reverse import reverse
from rest_framework.settings import api_settings
from rest_framework.views import APIView
from rest_framework.viewsets import ViewSet
from rest_framework_csv.renderers import CSVRenderer
from rest_framework_yaml.renderers import YAMLRenderer

from workshops.models import (
    Badge,
    Airport,
    Event,
    TodoItem,
    Tag,
    Organization,
    Task,
    Award,
    Person,
    is_admin,
)
from workshops.util import get_members, default_membership_cutoff

from .serializers import (
    PersonNameEmailUsernameSerializer,
    ExportBadgesSerializer,
    ExportBadgesByPersonSerializer,
    ExportInstructorLocationsSerializer,
    ExportEventSerializer,
    TimelineTodoSerializer,
    WorkshopsOverTimeSerializer,
    InstructorsOverTimeSerializer,
    InstructorNumTaughtSerializer,
    InstructorsByTimePeriodSerializer,
    OrganizationSerializer,
    EventSerializer,
    TaskSerializer,
    TodoSerializer,
    AirportSerializer,
    AwardSerializer,
    PersonSerializer,
)

from .filters import (
    EventFilter,
    TaskFilter,
    PersonFilter,
    InstructorsOverTimeFilter,
    WorkshopsOverTimeFilter,
    LearnersOverTimeFilter,
)


class IsAdmin(BasePermission):
    """This permission allows only admin users to view the API content."""
    def has_permission(self, request, view):
        return is_admin(request.user)


class QueryMetadata(SimpleMetadata):
    """Additionally include info about query parameters."""

    def determine_metadata(self, request, view):
        data = super().determine_metadata(request, view)

        try:
            data['query_params'] = view.get_query_params_description()
        except AttributeError:
            pass

        return data


class LargeResultsSetPagination(PageNumberPagination):
    page_size = 1000
    page_size_query_param = 'page_size'
    max_page_size = 10000


class StandardResultsSetPagination(PageNumberPagination):
    page_size = 100
    page_size_query_param = 'page_size'
    max_page_size = 1000


class ApiRoot(APIView):
    def get(self, request, format=None):
        return Response({
            'export-badges': reverse('api:export-badges', request=request,
                                     format=format),
            'export-badges-by-person': reverse('api:export-badges-by-person',
                                               request=request,
                                               format=format),
            'export-instructors': reverse('api:export-instructors',
                                          request=request, format=format),
            'export-members': reverse('api:export-members', request=request,
                                      format=format),
            'events-published': reverse('api:events-published',
                                        request=request, format=format),
            'user-todos': reverse('api:user-todos',
                                  request=request, format=format),
            'reports-list': reverse('api:reports-list',
                                    request=request, format=format),

            # "new" API list-type endpoints below
            'airport-list': reverse('api:airport-list', request=request,
                                    format=format),
            'person-list': reverse('api:person-list', request=request,
                                   format=format),
            'event-list': reverse('api:event-list', request=request,
                                  format=format),
            'organization-list': reverse('api:organization-list', request=request,
                                 format=format),
        })


class ExportBadgesView(ListAPIView):
    """List all badges and people who have them."""
    permission_classes = (IsAuthenticatedOrReadOnly, )
    paginator = None  # disable pagination

    queryset = Badge.objects.prefetch_related('award_set')
    serializer_class = ExportBadgesSerializer


class ExportBadgesByPersonView(ListAPIView):
    """List all badges and people who have them grouped by person."""
    permission_classes = (IsAuthenticatedOrReadOnly, )
    paginator = None  # disable pagination

    queryset = Person.objects.prefetch_related('badges')
    serializer_class = ExportBadgesByPersonSerializer


class ExportInstructorLocationsView(ListAPIView):<commit_msg>Export Badge views: improve queries performance<commit_after>import datetime
from itertools import accumulate

from django.db.models import Count, Sum, Case, F, When, Value, IntegerField, Min
from rest_framework import viewsets
from rest_framework.decorators import list_route
from rest_framework.filters import DjangoFilterBackend
from rest_framework.generics import ListAPIView
from rest_framework.metadata import SimpleMetadata
from rest_framework.pagination import PageNumberPagination
from rest_framework.permissions import (
    IsAuthenticatedOrReadOnly, IsAuthenticated, BasePermission
)
from rest_framework.renderers import BrowsableAPIRenderer, JSONRenderer
from rest_framework.response import Response
from rest_framework.reverse import reverse
from rest_framework.settings import api_settings
from rest_framework.views import APIView
from rest_framework.viewsets import ViewSet
from rest_framework_csv.renderers import CSVRenderer
from rest_framework_yaml.renderers import YAMLRenderer

from workshops.models import (
    Badge,
    Airport,
    Event,
    TodoItem,
    Tag,
    Organization,
    Task,
    Award,
    Person,
    is_admin,
)
from workshops.util import get_members, default_membership_cutoff

from .serializers import (
    PersonNameEmailUsernameSerializer,
    ExportBadgesSerializer,
    ExportBadgesByPersonSerializer,
    ExportInstructorLocationsSerializer,
    ExportEventSerializer,
    TimelineTodoSerializer,
    WorkshopsOverTimeSerializer,
    InstructorsOverTimeSerializer,
    InstructorNumTaughtSerializer,
    InstructorsByTimePeriodSerializer,
    OrganizationSerializer,
    EventSerializer,
    TaskSerializer,
    TodoSerializer,
    AirportSerializer,
    AwardSerializer,
    PersonSerializer,
)

from .filters import (
    EventFilter,
    TaskFilter,
    PersonFilter,
    InstructorsOverTimeFilter,
    WorkshopsOverTimeFilter,
    LearnersOverTimeFilter,
)


class IsAdmin(BasePermission):
    """This permission allows only admin users to view the API content."""
    def has_permission(self, request, view):
        return is_admin(request.user)


class QueryMetadata(SimpleMetadata):
    """Additionally include info about query parameters."""

    def determine_metadata(self, request, view):
        data = super().determine_metadata(request, view)

        try:
            data['query_params'] = view.get_query_params_description()
        except AttributeError:
            pass

        return data


class LargeResultsSetPagination(PageNumberPagination):
    page_size = 1000
    page_size_query_param = 'page_size'
    max_page_size = 10000


class StandardResultsSetPagination(PageNumberPagination):
    page_size = 100
    page_size_query_param = 'page_size'
    max_page_size = 1000


class ApiRoot(APIView):
    def get(self, request, format=None):
        return Response({
            'export-badges': reverse('api:export-badges', request=request,
                                     format=format),
            'export-badges-by-person': reverse('api:export-badges-by-person',
                                               request=request,
                                               format=format),
            'export-instructors': reverse('api:export-instructors',
                                          request=request, format=format),
            'export-members': reverse('api:export-members', request=request,
                                      format=format),
            'events-published': reverse('api:events-published',
                                        request=request, format=format),
            'user-todos': reverse('api:user-todos',
                                  request=request, format=format),
            'reports-list': reverse('api:reports-list',
                                    request=request, format=format),

            # "new" API list-type endpoints below
            'airport-list': reverse('api:airport-list', request=request,
                                    format=format),
            'person-list': reverse('api:person-list', request=request,
                                   format=format),
            'event-list': reverse('api:event-list', request=request,
                                  format=format),
            'organization-list': reverse('api:organization-list', request=request,
                                 format=format),
        })


class ExportBadgesView(ListAPIView):
    """List all badges and people who have them."""
    permission_classes = (IsAuthenticatedOrReadOnly, )
    paginator = None  # disable pagination

    queryset = Badge.objects.prefetch_related('award_set', 'award_set__person')
    serializer_class = ExportBadgesSerializer


class ExportBadgesByPersonView(ListAPIView):
    """List all badges and people who have them grouped by person."""
    permission_classes = (IsAuthenticatedOrReadOnly, )
    paginator = None  # disable pagination

    queryset = Person.objects.exclude(badges=None).prefetch_related('badges')
    serializer_class = ExportBadgesByPersonSerializer


class ExportInstructorLocationsView(ListAPIView):
{'fraction_non_alphanumeric': 0.07534516765285997, 'fraction_numerical': 0.003155818540433925, 'mean_word_length': 2.8735676088617264, 'pattern_counts': {'":': 0, '<': 3, '<?xml version=': 0, '>': 3, 'https://': 0, 'lorem ipsum': 0, 'www.': 0, 'xml': 0}, 'pii_count': 0, 'substrings_counts': 0, 'word_list_counts': {'cursed_substrings.json': 30, 'profanity_word_list.json': 0, 'sexual_word_list.json': 0, 'zh_pornsignals.json': 0}}
{'dir': 'git-commits-cleaned', 'id': '1295255', 'n_tokens_mistral': 2596, 'n_tokens_neox': 2516, 'n_words': 579}