views.py 3.1 KB

1234567891011121314151617181920212223242526272829303132333435363738394041424344454647484950515253545556575859606162636465666768697071727374757677787980818283848586
  1. # -*- coding: utf-8 -*-
  2. from __future__ import unicode_literals, division, print_function
  3. from rest_framework import viewsets
  4. from rest_framework.authentication import SessionAuthentication
  5. from rest_framework.permissions import AllowAny, IsAuthenticated
  6. from django.conf import settings
  7. from panorama.models import Point, Panorama, ReferencePoint, Reference
  8. from .serializers import *
  9. class CelutzApiLoginMixin(object):
  10. """Mixin that requires logging in to access the API if
  11. settings.LOGIN_REQUIRED is True, and does nothing otherwise. It
  12. allows to choose whether using celutz requires an account or is open
  13. to anybody.
  14. The standard way of specifying authentication and permission is to
  15. override the variable self.authentication_classes and
  16. self.permission_classes:
  17. http://www.django-rest-framework.org/api-guide/authentication/
  18. http://www.django-rest-framework.org/api-guide/permissions/
  19. However, since we want to configure this dynamically based on the
  20. settings, we directly override the internal methods. This means that
  21. upgrading Django-Rest-Framework might break this Mixin.
  22. """
  23. def get_authenticators(self):
  24. if settings.LOGIN_REQUIRED:
  25. return [SessionAuthentication()]
  26. else:
  27. return []
  28. def get_permissions(self):
  29. if settings.LOGIN_REQUIRED:
  30. return [IsAuthenticated()]
  31. else:
  32. return [AllowAny()]
  33. class ReferencePointViewSet(CelutzApiLoginMixin, viewsets.ModelViewSet):
  34. queryset = ReferencePoint.objects.all()
  35. serializer_class = ReferencePointSerializer
  36. def get_queryset(self):
  37. """
  38. Allow to filter reference points, by only considering those in a
  39. disc around a given geographic position.
  40. Example filter:
  41. /api/v1/refpoints/?lat=42&lon=42&dist=10000
  42. returns all reference points around (42°, 42°) at less than 10
  43. kilometers.
  44. """
  45. queryset = ReferencePoint.objects.all()
  46. lat = self.request.query_params.get('lat', None)
  47. lon = self.request.query_params.get('lon', None)
  48. # In meters
  49. distance = self.request.query_params.get('dist', None)
  50. if distance is not None:
  51. distance = int(distance)
  52. else:
  53. distance = settings.PANORAMA_MAX_DISTANCE
  54. if lat is not None and lon is not None:
  55. p = Point(float(lat), float(lon), 0)
  56. # Filter refpoints based on their (great circle) distance to
  57. # the parameter point. The database can't do it, so we load
  58. # all objects and filter them in Python.
  59. refpoints = [refpoint.id for refpoint in ReferencePoint.objects.all()
  60. if p.great_circle_distance(refpoint) <= distance]
  61. queryset = queryset.filter(id__in=refpoints)
  62. return queryset
  63. class PanoramaViewSet(CelutzApiLoginMixin, viewsets.ModelViewSet):
  64. queryset = Panorama.objects.all()
  65. serializer_class = PanoramaSerializer
  66. class ReferenceViewSet(CelutzApiLoginMixin, viewsets.ModelViewSet):
  67. queryset = Reference.objects.all()
  68. serializer_class = ReferenceSerializer