Write an API for Almost Anything DjangoCon 2017 The Amazing Power and Flexibility of Django Rest Framework
Who Am I? ●Web Developer at Caktus Group ●Organizer of PyLadies RDU ●Builder and User of APIs Note: Slides available at: http://cakt.us/DjangoCon2017talk
What does “API” mean, anyway? ● “Application Programming Interface” ● Definition (techtarget.com): “An application program interface (API) is code that allows two software programs to communicate with each other.”
Why Are APIs Useful? ●Flexibility ●Access (internally and externally) ●Future-proofing
Example: Customized Output ●Massage therapist needed schedule information to be sharable without client information ●Scheduling software did not do this ○But did have an API!
Example: Customized Output ●Small script can pull schedule information and post without client information to a shareable calendar ●API made it possible to create an otherwise nonexistent feature
APIs for Non-Web Applications ●Easy and practical enough to be useful for other distributed applications ●Example: Game back-end ○https://github.com/flowerncsu/ecgc-2017
Internal Separation ●Dynamic, highly interactive pages require JavaScript ●Use API to separate Django code from JavaScript code
Internal Separation ●Cleaner code ●Easier to use JS frameworks ●Retrieve data and context with simple requests
APIs Are Awesome, So How Do I Build One?
Building an API ●Many ways, many packages ●Django Rest Framework ○Sits nicely on top of existing Django code ○Very thorough feature set
Anatomy of Django Rest Framework API Router ViewSet Serializer Django Models/ Database serializers.py views.py urls.py
Anatomy of Django Rest Framework API Serializer Django Models/ Database
Building the Serializer from rest_framework import serializers from .models import MyModel class MyModelSerializer(serializers.ModelSerializer): class Meta: model = MyModel fields = ( 'id', 'name', 'category', )
Anatomy of Django Rest Framework API ViewSet Serializer Django Models/ Database
Building the ViewSet from rest_framework import viewsets from .models import MyModel from .serializers import MyModelSerializer class MyModelViewSet(viewsets.ModelViewSet): """ API endpoint that allows MyModel instances to be viewed or edited. """ queryset = MyModel.objects.all() serializer_class = MyModelSerializer
Anatomy of Django Rest Framework API Router ViewSet Serializer Django Models/ Database
Building URLs with the Router from django.conf.urls import url, include from rest_framework import routers from myapp import views as myapp_api router = routers.DefaultRouter() router.register(r'mymodel', myapp_api.MyModelViewSet) urlpatterns = [ url(r'^', include(router.urls)), url(r'^api-auth/', include('rest_framework.urls', namespace='rest_framework')) ]
Accessing the API HTTP Methods Operations ●C ●R ●U ●D
Accessing the API HTTP Methods ● POST Operations ●Create ●R ●U ●D
Accessing the API HTTP Methods ● POST ● GET Operations ●Create ●Read ●U ●D
Accessing the API HTTP Methods ● POST ● GET ● PUT ● PATCH Operations ●Create ●Read ●Update ●D
Accessing the API HTTP Methods ● POST ● GET ● PUT ● PATCH ● DELETE Operations ●Create ●Read ●Update ●Delete
Accessing the API HTTP Methods ● POST ● GET ● PUT ● PATCH ● DELETE Operations ●Create ●Read ●Update ●Delete
Accessing the API router.register(r'mymodel', myapp_api.MyModelViewSet) (GET) myapp.com/mymodel -> List of instances, fields based on serializer (POST) myapp.com/mymodel -> Create a new instance (GET) myapp.com/mymodel/instance_id -> Get details for instance with instance_id (DELETE) myapp.com/mymodel/instance_id -> Delete instance with instance_id More information: http://www.django-rest-framework.org/api-guide/viewsets/
What If I Don’t Want Users Doing That? Several options to protect data: ●Authentication ●Read-only Viewsets ●Restricting specific actions
Documentation ●Key to usability of the API ●Structure is predictable ○URL and HTTP method ○Operation performed at that URL/method ○Parameters expected ○Data format returned More information: http://www.django-rest-framework.org/topics/documenting-your-api/
Automatic Documentation from rest_framework.documentation import include_docs_urls ... urlpatterns = [ ... url(r'^docs/', include_docs_urls(title='My API')) ] More information: http://www.django-rest-framework.org/topics/documenting-your-api/
Tests ● API functionality can be tested simply ●Automated tests mean “set it and forget it” ●Test failures can highlight changes that should be reflected in documentation
Sample Test from rest_framework.test import APITestCase class TestMyModelViewSet(APITestCase): def setUp(self): self.url = reverse('mymodel-list') self.instances = [MyModel() for i in range(3)] for item in self.instances: item.save() def test_list_view(self): response = self.client.get(self.url, format='json') self.assertEqual(response.status_code, 200) self.assertEqual(len(response.data), 3) More information: http://www.django-rest-framework.org/api-guide/testing/
Sample Test def test_can_create(self): data = {'name': 'test name', 'category': 1} response = self.client.post( self.url, data, format='json') self.assertEqual(response.status_code, 201) def test_detail_view(self): sample_id = MyModel.objects.first().id detail_url = self.url + '/' + str(sample_id) response = self.client.get(detail_url, format='json') self.assertEqual(response.status_code, 200) More information: http://www.django-rest-framework.org/api-guide/testing/
Homework! ●What Django projects do you have live? ○In development? ●Do they have public information? ●Collections of user data? ●Can’t think of a use? Users will!
Resources Django Rest Framework Quickstart: http://www.django-rest-framework.org/tutorial/quickstart/ Example Project: https://github.com/flowerncsu/ecgc-2017 These Slides: http://cakt.us/DjangoCon2017talk Caktus Group: @caktusgroup https://www.caktusgroup.com/ My Twitter: @charlottecodes

Write an API for Almost Anything: The Amazing Power and Flexibility of Django Rest Framework

  • 1.
    Write an APIfor Almost Anything DjangoCon 2017 The Amazing Power and Flexibility of Django Rest Framework
  • 2.
    Who Am I? ●WebDeveloper at Caktus Group ●Organizer of PyLadies RDU ●Builder and User of APIs Note: Slides available at: http://cakt.us/DjangoCon2017talk
  • 3.
    What does “API”mean, anyway? ● “Application Programming Interface” ● Definition (techtarget.com): “An application program interface (API) is code that allows two software programs to communicate with each other.”
  • 4.
    Why Are APIsUseful? ●Flexibility ●Access (internally and externally) ●Future-proofing
  • 5.
    Example: Customized Output ●Massagetherapist needed schedule information to be sharable without client information ●Scheduling software did not do this ○But did have an API!
  • 6.
    Example: Customized Output ●Smallscript can pull schedule information and post without client information to a shareable calendar ●API made it possible to create an otherwise nonexistent feature
  • 7.
    APIs for Non-WebApplications ●Easy and practical enough to be useful for other distributed applications ●Example: Game back-end ○https://github.com/flowerncsu/ecgc-2017
  • 8.
    Internal Separation ●Dynamic, highlyinteractive pages require JavaScript ●Use API to separate Django code from JavaScript code
  • 9.
    Internal Separation ●Cleaner code ●Easierto use JS frameworks ●Retrieve data and context with simple requests
  • 10.
    APIs Are Awesome,So How Do I Build One?
  • 11.
    Building an API ●Manyways, many packages ●Django Rest Framework ○Sits nicely on top of existing Django code ○Very thorough feature set
  • 12.
    Anatomy of DjangoRest Framework API Router ViewSet Serializer Django Models/ Database serializers.py views.py urls.py
  • 13.
    Anatomy of DjangoRest Framework API Serializer Django Models/ Database
  • 14.
    Building the Serializer fromrest_framework import serializers from .models import MyModel class MyModelSerializer(serializers.ModelSerializer): class Meta: model = MyModel fields = ( 'id', 'name', 'category', )
  • 15.
    Anatomy of DjangoRest Framework API ViewSet Serializer Django Models/ Database
  • 16.
    Building the ViewSet fromrest_framework import viewsets from .models import MyModel from .serializers import MyModelSerializer class MyModelViewSet(viewsets.ModelViewSet): """ API endpoint that allows MyModel instances to be viewed or edited. """ queryset = MyModel.objects.all() serializer_class = MyModelSerializer
  • 17.
    Anatomy of DjangoRest Framework API Router ViewSet Serializer Django Models/ Database
  • 18.
    Building URLs withthe Router from django.conf.urls import url, include from rest_framework import routers from myapp import views as myapp_api router = routers.DefaultRouter() router.register(r'mymodel', myapp_api.MyModelViewSet) urlpatterns = [ url(r'^', include(router.urls)), url(r'^api-auth/', include('rest_framework.urls', namespace='rest_framework')) ]
  • 19.
    Accessing the API HTTPMethods Operations ●C ●R ●U ●D
  • 20.
    Accessing the API HTTPMethods ● POST Operations ●Create ●R ●U ●D
  • 21.
    Accessing the API HTTPMethods ● POST ● GET Operations ●Create ●Read ●U ●D
  • 22.
    Accessing the API HTTPMethods ● POST ● GET ● PUT ● PATCH Operations ●Create ●Read ●Update ●D
  • 23.
    Accessing the API HTTPMethods ● POST ● GET ● PUT ● PATCH ● DELETE Operations ●Create ●Read ●Update ●Delete
  • 24.
    Accessing the API HTTPMethods ● POST ● GET ● PUT ● PATCH ● DELETE Operations ●Create ●Read ●Update ●Delete
  • 25.
    Accessing the API router.register(r'mymodel',myapp_api.MyModelViewSet) (GET) myapp.com/mymodel -> List of instances, fields based on serializer (POST) myapp.com/mymodel -> Create a new instance (GET) myapp.com/mymodel/instance_id -> Get details for instance with instance_id (DELETE) myapp.com/mymodel/instance_id -> Delete instance with instance_id More information: http://www.django-rest-framework.org/api-guide/viewsets/
  • 26.
    What If IDon’t Want Users Doing That? Several options to protect data: ●Authentication ●Read-only Viewsets ●Restricting specific actions
  • 27.
    Documentation ●Key to usabilityof the API ●Structure is predictable ○URL and HTTP method ○Operation performed at that URL/method ○Parameters expected ○Data format returned More information: http://www.django-rest-framework.org/topics/documenting-your-api/
  • 28.
    Automatic Documentation from rest_framework.documentationimport include_docs_urls ... urlpatterns = [ ... url(r'^docs/', include_docs_urls(title='My API')) ] More information: http://www.django-rest-framework.org/topics/documenting-your-api/
  • 29.
    Tests ● API functionalitycan be tested simply ●Automated tests mean “set it and forget it” ●Test failures can highlight changes that should be reflected in documentation
  • 30.
    Sample Test from rest_framework.testimport APITestCase class TestMyModelViewSet(APITestCase): def setUp(self): self.url = reverse('mymodel-list') self.instances = [MyModel() for i in range(3)] for item in self.instances: item.save() def test_list_view(self): response = self.client.get(self.url, format='json') self.assertEqual(response.status_code, 200) self.assertEqual(len(response.data), 3) More information: http://www.django-rest-framework.org/api-guide/testing/
  • 31.
    Sample Test def test_can_create(self): data= {'name': 'test name', 'category': 1} response = self.client.post( self.url, data, format='json') self.assertEqual(response.status_code, 201) def test_detail_view(self): sample_id = MyModel.objects.first().id detail_url = self.url + '/' + str(sample_id) response = self.client.get(detail_url, format='json') self.assertEqual(response.status_code, 200) More information: http://www.django-rest-framework.org/api-guide/testing/
  • 32.
    Homework! ●What Django projectsdo you have live? ○In development? ●Do they have public information? ●Collections of user data? ●Can’t think of a use? Users will!
  • 33.
    Resources Django Rest FrameworkQuickstart: http://www.django-rest-framework.org/tutorial/quickstart/ Example Project: https://github.com/flowerncsu/ecgc-2017 These Slides: http://cakt.us/DjangoCon2017talk Caktus Group: @caktusgroup https://www.caktusgroup.com/ My Twitter: @charlottecodes