$30 off During Our Annual Pro Sale. View Details »

UnRESTful APIs at PyLadies SF

UnRESTful APIs at PyLadies SF

An overview of API design practices where RPC API calls are embedded in a REST API.

Ari Lacenski

June 25, 2013
Tweet

More Decks by Ari Lacenski

Other Decks in Programming

Transcript

  1. UnRESTful APIs
    with Django
    Ari Lacenski
    @tensory
    June 25, 2013
    Tuesday, June 25, 13

    View Slide

  2. Why create an API?
    API stands for Application Programming Interface.
    An API to your project lets people write applications
    that use your technology.
    Web APIs are collections of URLs pointing to services.
    Tuesday, June 25, 13

    View Slide

  3. Remote Procedure Call
    Uses URL patterns to suggest what you get back
    like: yoursite.com/show/articles?article_id=42
    Used to be super common, until REST pattern emerged
    good luck with that
    Often inconsistent &
    needs a lot of docs
    Response data isn’t
    linked to DB records
    Tuesday, June 25, 13

    View Slide

  4. REST
    (REpresentational State Transfer)
    Uses HTTP concepts: GET, POST, DELETE & PUT
    Super useful, super popular!
    Lets you build an API that directly represents the data
    that you want developers to work with
    Tuesday, June 25, 13

    View Slide

  5. REST
    GET /article/42 returns JSON representation of article
    with id=42
    POST /article/ gets back JSON with a saved article ID
    GET /article/ gets back a list of article IDs
    { ‘article’: { ‘id’: 42, ‘author’: ‘Becky
    Smith’, ‘title’: ‘API Design 101’ }}
    Tuesday, June 25, 13

    View Slide

  6. REST works great.
    “RESTful API” designs try to follow the REST pattern.
    There are free API libraries for Python web frameworks.
    This all works well for creating APIs to relational data.
    BUT WAIT
    What if your data is too complex to store in a DB table?
    Tuesday, June 25, 13

    View Slide

  7. Extend your pattern.
    Consider a photo service with some color search tools.
    Upload a photo? POST to /upload/ with file + metadata
    Get photo details? GET /photo/
    Want to let your API users calculate the average color in
    some random images? ... Hmm.
    Tuesday, June 25, 13

    View Slide

  8. Let’s make it happen.
    Tuesday, June 25, 13

    View Slide

  9. models.py
    from django.db import models
    class Photo(models.Model):
    uploader = models.ForeignKey(User)
    uploaded_at = models.DateTimeField()
    file = models.FileField(blank=True, null=True)
    How do you turn this model into an API?
    Try Tastypie.
    Tuesday, June 25, 13

    View Slide

  10. from tastypie.resources import Resource
    from models import Photo
    class PhotoResource(Resource):
    class Meta(object):
    queryset = Photo.objects.all()
    resource_name = ‘photo’
    allowed_methods = [‘get’, ‘post’, ‘put’]
    api.py
    Tuesday, June 25, 13

    View Slide

  11. urls.py
    from tastypie.api import Api
    from api import PhotoResource
    photo_api = Api(api_name='api')
    urlpatterns = patterns(‘’, include(photo_api.urls))
    # ... other routes in your app can go
    # into this urlpatterns definition, if you want
    Tuesday, June 25, 13

    View Slide

  12. Can we upload photos?
    Can we get back one photo’s data?
    Can we see data about all photos
    we’ve uploaded?
    Yup.
    Sure.
    Check it out.
    GET /api/photo/42
    GET /api/photo/
    POST /api/photo/
    Where are we now?
    Tuesday, June 25, 13

    View Slide

  13. But what about that
    color method?
    id=34
    id=60
    id=29
    Tuesday, June 25, 13

    View Slide

  14. 1. In api.py, add a method to your API’s
    PhotoResource.
    2. In views.py, create any helper methods you need
    for your Photo model.
    3. In api.py, use prepend_urls to add an RPC URL
    pattern for the new PhotoResource method.
    Mix in an RPC URL.
    Tuesday, June 25, 13

    View Slide

  15. import views
    from tastypie.resources import Resource
    from models import Photo
    class PhotoResource(Resource):
    class Meta(object):
    queryset = Photo.objects.all()
    resource_name = ‘photo’
    allowed_methods = [‘get’, ‘post’, ‘put’]
    def prepend_urls(self):
    return [
    url(r”^(?P)/average/” %
    self._meta.resource_name, self.wrap_view('get_average_color'))
    ]
    def get_average_color(self, request):
    photo_ids = request.getlist(‘ids’)
    # Add a get_average_color method to your app views.
    result = views.get_average_color(photo_ids)
    return { ‘color’: result.color_code }
    api.py
    Tuesday, June 25, 13

    View Slide

  16. You’re done!
    GET /api/photo/average?ids=34,60,29
    { ‘color’: ‘BAB5B2’ }
    Tuesday, June 25, 13

    View Slide

  17. Find out more
    Comparison of REST vs XML RPC
    http://bit.ly/8lkoPK
    Django API packages comparison
    https://www.djangopackages.com/grids/g/api/
    Tastypie
    http://django-tastypie.readthedocs.org/
    https://github.com/toastdriven/django-tastypie
    Tuesday, June 25, 13

    View Slide

  18. Thanks for listening!
    Ari Lacenski @tensory
    Tuesday, June 25, 13

    View Slide