Post on 18-Jun-2015
description
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