DJANGO-REST-FRAMEWORK: AWESOME WEB-BROWSABLE WEB APIS

Preview:

DESCRIPTION

Palestra ministrada por Filipe Ximenes e Fernando Rocha na PythonBrasil[9]

Citation preview

DJANGO-REST-FRAMEWORKAWESOME WEB-BROWSABLE WEB APIS

por e Filipe Ximenes Fernando Rocha

Developer @ thinkrApaixonado por Python

Entusiasta de Software LivreInteressado em web e infraestrutura.

THINKR

Fundador da VintaDesenvolvedor Web

Apaixonado por aprenderFã de comunidades de Sofware Livre

Curioso de empreendedorismo

DJANGO-REST-FRAMEWORK

AWESOME WEB-BROWSABLE WEB API'S

API (APPLICATION PROGRAMMING INTERFACE)

Uma Interface de Programação de Aplicação especifica comocertos componentes de software devem interagir uns com os

outros.

DJANGO-REST-FRAMEWORK

AWESOME WEB-BROWSABLE WEB API'S

MÉTODOS HTTPGETPOST

MÉTODOS HTTP (RFC 2616)GETPOSTHEADPUTDELETEOPTIONSTRACECONNECT

RESTFULL API

Utiliza todo o potencial do HTTP para servir recursos através demétodos (verbos)

EXEMPLO/user_list/user_create/user?id=xxx/user_edit?id=xxx/user_delete?id=xxx

EXEMPLO RESTFULLGET /userPOST /userGET /user/idPUT /user/idDELETE /user/id

DJANGO-REST-FRAMEWORKAWESOME WEB-BROWSABLE WEB API'S

DJANGO-REST-FRAMEWORKÉ um conjunto de ferramentas construidas a partir do Django

que facilitam a construção de API's REST

NÚMEROSCriador - Tom ChristieEstrelas - 1592Forks - 464Documentação

UMA VIEW SIMPLES

APIVIEWfrom rest_framework.views import APIViewfrom rest_framework.response import Responsefrom rest_framework.renderers import JSONRenderer

class PalestrantesView(APIView): renderer_classes = (JSONRenderer,)

def get(self, request, *args, **kwargs): data = [{'nome': 'Filipe', 'cidade': 'Recife', 'empresa': 'Vinta'}, {'nome': 'Fernando', 'cidade': 'Recife', 'empresa': 'Thinkr'}]

return Response(data)

RESPOSTAHTTP/1.1 200 OKContent-Type:application/json

[ { cidade: "Recife", empresa: "Vinta", nome: "Filipe" }, { cidade: "Recife", empresa: "Thinkr", nome: "Fernando" }]

RENDERIZADORES

DA PYTHON PARA TEXTOJSONRenderer

UnicodeJSONRenderer

JSONPRenderer

YAMLRenderer

XMLRenderer

TemplateHTMLRenderer

StaticHTMLRenderer

HTMLFormRenderer

BrowsableAPIRenderer

#BaseRenderer

JSONrenderer_classes = (JSONRenderer,)

HTTP/1.1 200 OKContent-Type:application/json

[ { "nome": "Filipe", "cidade": "Recife", "empresa": "Vinta" }, { "nome": "Fernando", "cidade": "Recife", "empresa": "Thinkr" }]

XMLrenderer_classes = (XMLRenderer,)

HTTP/1.1 200 OKContent-Type:application/xml

<?xml version="1.0" encoding="utf-8"?><root> <list-item> <cidade>Recife</cidade> <empresa>Vinta</empresa> <nome>Filipe</nome> </list-item> <list-item> <cidade>Recife</cidade> <empresa>Thinkr</empresa> <nome>Fernando</nome> </list-item></root>

BROWSABLE APIrenderer_classes = (BrowsableAPIRenderer,)

PARSERS

DE TEXTO PARA PYTHONJSONParser

YAMLParser

XMLParser

FormParser

MultiPartParser

FileUploadParser

#BaseParser

AUTENTICAÇÃO

BASTA DECLARARfrom rest_framework.views import APIViewfrom rest_framework.response import Responsefrom rest_framework.authentication import SessionAuthentication, \ TokenAuthentication

class PalestrantesView(APIView): authentication_classes = (SessionAuthentication, TokenAuthentication,) permission_classes = (IsAuthenticated,)

def get(self, request, *args, **kwargs): data = [{'nome': 'Filipe', 'cidade': 'Recife', 'empresa': 'Vinta'}, {'nome': 'Fernando', 'cidade': 'Recife', 'empresa': 'Thinkr'}] return Response(data)

FALHA NA AUTENTICAÇÃOHTTP/1.0 401 OK

HTTP_401_UNAUTHORIZEDHTTP/1.0 403 OK

HTTP_403_FORBIDDEN

AUTENTICAÇÃO PLUGÁVELBasicAuthentication

TokenAuthentication

SessionAuthentication

OAuthAuthentication

OAuth2Authentication

#BaseAuthentication

DEFININDO DEFAULT NO SETTINGSREST_FRAMEWORK = { 'DEFAULT_AUTHENTICATION_CLASSES': ( 'rest_framework.authentication.SessionAuthentication', 'rest_framework.authentication.TokenAuthentication' ),}

SIMPLIFICANDO A VIEW

GENERICAPIVIEWmodels.py

from django.db import models

class Speaker(models.Model): name = models.CharField(u'Nome', max_length=50) city = models.CharField(u'Cidade', max_length=50) company = models.CharField(u'Empresa', max_length=50) phone = models.CharField(u'Telefone', max_length=12, blank=True)

views.pyfrom rest_framework import genericsfrom .models import Speaker

class SpeakerList(generics.ListCreateAPIView): ''' Endpoint que representa a lista de palestrantes, e permite que novos palestrantes sejam cadastrados. ''' model = Speaker

GET /SPEAKERS/HTTP/1.0 200 OKAllow: GET, POST, HEAD, OPTIONSContent-Type: application/json; charset=utf-8

[ { "city": "Recife", "company": "Thinkr", "id": 1, "name": "Fernando Rocha", "phone": "12345678" }, { "city": "Recife", "company": "Vinta", "id": 2, "name": "Filipe Ximenes", "phone": "12345678" }]

POST /SPEAKERS/request

{}

responseHTTP/1.0 400 BAD REQUESTAllow: GET, POST, HEAD, OPTIONSContent-Type: application/json; charset=utf-8

{ "city": [ "This field is required." ], "company": [ "This field is required." ], "name": [ "This field is required." ]}

POST /SPEAKERS/request

{'name': 'Daker', 'company': 'INTD', 'phone': '313131'}

responseHTTP/1.0 201 CREATEDAllow: GET, POST, HEAD, OPTIONSContent-Type: application/json; charset=utf-8

{ "city": "Recife", "company": "INTD", "id": 3, "name": "Daker" "phone": "313131"}

GENERIC VIEWSCreateAPIView

ListAPIView

RetrieveAPIView

DestroyAPIView

UpdateAPIView

ListCreateAPIView

RetrieveUpdateAPIView

RetrieveDestroyAPIView

RetrieveUpdateDestroyAPIView

CUSTOMIZANDO OS DADOS(SERIALIZADORES)

SERIALIZADORESConverte objetos de Python para listas e dicionáriosConverte dicionários e listas para objetos de PythonSemelhante a API de forms do Django

DEFININDO CAMPOSserializers.py

from rest_framework import serializersfrom .models import Speaker

class SpeakerSerializer(serializers.ModelSerializer): class Meta: model = Speaker fields = ('name', 'city', 'company')

UTILIZANDO GENERIC VIEWSserializers.py

from rest_framework import serializersfrom .models import Speaker

class SpeakerSerializer(serializers.ModelSerializer): class Meta: model = Speaker fields = ('name', 'city', 'company')

views.pyfrom rest_framework import genericsfrom .models import Speaker

class SpeakerList(generics.ListCreateAPIView): ''' Endpoint que representa a lista de palestrantes, e permite que novos palestrantes sejam cadastrados. ''' model = Speaker serializer_class = SpeakerSerializer

GET /SPEAKERS/HTTP/1.0 200 OKAllow: GET, POST, HEAD, OPTIONSContent-Type: application/json; charset=utf-8

[ { "city": "Recife", "company": "thinkr", "name": "Fernando Rocha," }, { "city": "Recife", "company": "Vinta", "name": "Filipe Ximenes," }, { "city": "Recife", "company": "INTD", "name": "Daker," }]

COMO FUNCIONA?views.py

from rest_framework import genericsfrom rest_framework.response import Responsefrom .models import Speaker

class SpeakerList(generics.APIView): ''' Endpoint que representa a lista de palestrantes, e permite que novos palestrantes sejam cadastrados. ''' def post(self, request): serializer = SpeakerSerializer(data=request.DATA)

if serializer.is_valid(): serializer.save() return Response(serializer.data, status=201) return Response(serializer.errros, status=400)

VALIDAÇÃOserializers.py

from rest_framework import serializersfrom .models import Speaker

class SpeakerSerializer(serializers.ModelSerializer): class Meta: model = Speaker fields = ('name', 'city', 'company')

def validate_name(self, attrs, source): if len(attrs[source].split()) < 2: raise serializers.ValidationError(u'Informe o nome e sobrenome') return attrs

POST /SPEAKERS/request

{'name': 'a', 'city': 'recife', 'company': 'test'}

responseHTTP/1.0 400 BAD REQUESTAllow: GET, POST, HEAD, OPTIONSContent-Type: application/json; charset=utf-8

{ "name": [ "Informe o nome e sobrenome" ]}

GET /SPEAKERS/HTTP/1.0 200 OKAllow: GET, POST, HEAD, OPTIONSContent-Type: application/json; charset=utf-8

[ { "city": "Recife", "company": "THINKR", "name": "Fernando Rocha," }, { "city": "Recife", "company": "VINTA", "name": "Filipe Ximenes," }, { "city": "Recife", "company": "INTD", "name": "Daker," }, ]

VIEWSETS

VIEWSETviews.py

from rest_framework import viewsetsfrom .models import Speaker

class SpeakerViewSet(viewsets.ModelViewSet): ''' Endpoint para visualizer e editar instâncias de Speaker ''' serializer_class = UserSerializer queryset = Speaker.objects.all()

FILIPE XIMENESgithub.com/filipeximenes

twitter.com/xima

FERNANDO ROCHAlivingintheshell.com

github.com/fernandogrdtwitter.com/fernandogrd