pulseapi/creators/views.py (53 lines of code) (raw):
from itertools import chain
from django.db.models import Q
from django.conf import settings
from django_filters.rest_framework import DjangoFilterBackend
from rest_framework import exceptions
from rest_framework.filters import BaseFilterBackend
from rest_framework.generics import ListAPIView
from rest_framework.pagination import PageNumberPagination
from pulseapi.profiles.models import UserProfile
from pulseapi.creators.serializers import CreatorSerializer
class CreatorsPagination(PageNumberPagination):
"""
Add support for pagination and custom page size
"""
# page size decided in https://github.com/mozilla/network-pulse-api/issues/228
page_size = 6
page_size_query_param = 'page_size'
max_page_size = 20
class FilterCreatorNameBackend(BaseFilterBackend):
def filter_queryset(self, request, queryset, view):
search_term = request.query_params.get('name', None)
if not search_term:
return queryset
profile_custom = Q(custom_name__istartswith=search_term)
profile_name = Q(related_user__name__istartswith=search_term)
istartswith_filter = profile_custom | profile_name
qs = queryset.filter(istartswith_filter)
# If the number of results returned is less than the allowed
# page_size, we can instead rerun this using `contains` rules,
# rather than using the `startswith` rule.
page_size_query = request.query_params.get('page_size', None)
page_size = int(page_size_query if page_size_query else CreatorsPagination.page_size)
flen = len(qs)
if flen < page_size:
profile_custom = Q(custom_name__icontains=search_term)
profile_name = Q(related_user__name__icontains=search_term)
icontains_filter = profile_custom | profile_name
icontains_qs = queryset.filter(icontains_filter).exclude(istartswith_filter)
# make sure we keep our exact matches at the top of the result list
qs = list(chain(qs, icontains_qs))
return qs
class CreatorListView(ListAPIView):
"""
A view that permits a GET to allow listing all creators in the database
Note
----
This view only exists for backwards-compatibility (version 1). Creators no longer exist as independent models
and hence the pulseapi.profiles.views.UserProfileListAPIView should be used instead.
**Route** - `/creators`
#Query Parameters -
- ?name= - a partial match filter based on the start of the creator name.
"""
queryset = UserProfile.objects.active().order_by('id')
pagination_class = CreatorsPagination
serializer_class = CreatorSerializer
filter_backends = (
DjangoFilterBackend,
FilterCreatorNameBackend,
)
search_fields = (
'^name',
)
def get(self, request, *args, **kwargs):
if request.version == settings.API_VERSIONS['version_1']:
return super().get(request, *args, **kwargs)
raise exceptions.NotFound(
'The {path} route has been deprecated and is no longer supported in version {version}'.format(
path=request.path,
version=request.version
)
)