-
Notifications
You must be signed in to change notification settings - Fork 13
/
Copy pathDjangoRestFramework.txt
executable file
·484 lines (372 loc) · 13.5 KB
/
DjangoRestFramework.txt
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
309
310
311
312
313
314
315
316
317
318
319
320
321
322
323
324
325
326
327
328
329
330
331
332
333
334
335
336
337
338
339
340
341
342
343
344
345
346
347
348
349
350
351
352
353
354
355
356
357
358
359
360
361
362
363
364
365
366
367
368
369
370
371
372
373
374
375
376
377
378
379
380
381
382
383
384
385
386
387
388
389
390
391
392
393
394
395
396
397
398
399
400
401
402
403
404
405
406
407
408
409
410
411
412
413
414
415
416
417
418
419
420
421
422
423
424
425
426
427
428
429
430
431
432
433
434
435
436
437
438
439
440
441
442
443
444
445
446
447
448
449
450
451
452
453
454
455
456
457
458
459
460
461
462
463
464
465
466
467
468
469
470
471
472
473
474
475
476
477
478
479
480
481
482
483
484
=================================
Guía Django Rest Framework by dM
=================================
======
Teoría
======
DRF Es una librería que nos permite construir un API REST sobre Django de forma
sencilla. Ofreciendo una alta gama de métodos y funciones para el manejo,
definición y control de nuestros recursos.
==================
Qué es un API REST
==================
API, por sus siglas en inglés (Application Programming Interface). Básicamente,
representan una colección de métodos y funciones implementadas en un sistema con
el fin de que las mismas sean utilizadas por otros.
A medida que surgieron APIs sobre aplicaciones y plataformas web, se fue
formando el término API REST, el cual se usa para denominar a las API que están
implementadas bajo el protocolo HTTP. En otras palabras, un API REST permite el
uso de un servicio(función o método) perteneciente a una plataforma a un usuario
externo para que el mismo lo use en una aplicación propia. Puede ocurrir el caso
que ese usuario externo también seamos nosotros mismos.
============
Los recursos
============
Un recurso básicamente representa una sección, archivo o contenido que deseamos
obtener o modificar de una plataforma web a través de su API REST. Los mismos
serán identificados por una URI, la cuál nos ayudará a obtener/modificar el
mismo.
Las URI’s deben cumplir con ciertas características:
No deben llevar un verbo que implique una acción
Incorrecto: /recursos/id/editar
Correcto: /recursos/id/
Deben identificar solo a un recurso, deben ser únicas.
No deben tomar en cuenta el formato en la construcción de la URI
Incorrecto: /recursos/archivo.pdf
Correcto: /recursos/archivo
Deben mantener una jerarquía lógica.
Incorrecto: /apartamentos/2/edificio/3
Correcto: /edificios/3/apartamentos/2
Los filtrados de información deben hacerse mediante los parámetros HTTP
Incorrecto: /edificios/3/apartamentos/2/orden/asc
Correcto: /edificios/3/apartamentos/2/?orden=asc
Deben especificarse usando su forma plural
Incorrecto: /apartamento/2/
Correcto: /apartamentos/2/
=============================================================
Semántica de los métodos HTTP (GET, POST, PUT, PATCH, DELETE)
=============================================================
Una vez conocidas las principales reglas a la hora de construir nuestras URIs,
pasamos al siguiente paso, darle un significado semántico o de acción a los
métodos HTTP. Ampliando nuestro camino un poco más allá de los dos métodos más
utilizados comúnmente: GET y POST.
Los métodos serían los siguientes:
GET: Para consultar y leer recursos
POST: Para crear recursos
PUT: Para editar recursos
DELETE: Para eliminar recursos.
PATCH: Para editar partes concretas de un recurso.
=======================
Instalación del paquete
=======================
$ pip install djangorestframework
Agregamos el paquete a las aplicaciones instaladas en el settings.py
INSTALLED_APPS = [
.
'rest_framework',
]
=====================================
Hello world con Django Rest Framework
=====================================
Agregamos el paquete a las aplicaciones instaladas en el settings.py
INSTALLED_APPS = [
.
'rest_framework',
]
---
"""
En urls.py de alguna aplicación declaramos una url sencilla que llame a una
clase.
"""
# -*- coding: utf-8 -*-
from django.conf.urls import *
from django.contrib import admin
from app import views
urlpatterns = [
url(r'^', views.TestView.as_view(), name='test-view'),
]
---
"""
En views.py declaramos una clase para mostrar un respuesta http, visitamos
localhost para ver la respuesta. En este caso un hello REST World.
"""
# -*- coding: utf-8 -*-
from rest_framework.views import APIView
from rest_framework.response import Response
class TestView(APIView):
"""
Our First REST API for GET Requests
"""
def get(self, request, format=None):
return Response({'detail': "Hello REST World"})
---
Corremos el servidor de desarrollo y visitamos la url que sirva, debemos ver
nuestro mensaje.
===================
La clase Serializer
===================
Para comenzar una API Web es necesario tener una forma de serializar y
deserializar las instancias de los modelos en representaciones como JSON.
Serializar significa tomar los objetos que provengan de los modelos para
manipularlos y mostrarlos en el formato que se requiera, generalmente json a
traves de una url.
Podemos hacer esto declarando serializadores que trabajan muy similar a los
formularios de Django. Crea un archivo en el directorio de alguna aplicación un
fichero llamado serializers.py
====================================
Serializando el model user de django
====================================
En las urls.py de alguna app
# -*- coding: utf-8 -*-
from django.conf.urls import *
from django.contrib import admin
from series import views
urlpatterns = [
url(r'^users/$', views.user_list),
]
In serializer.py
# -*- coding: utf-8 -*-
from rest_framework import serializers
from django.contrib.auth.models import User
from .models import Serie
class UserSerializer(serializers.HyperlinkedModelSerializer):
class Meta:
model = User
fields = ('id', 'username', 'email', 'first_name', 'last_name', 'is_superuser', 'is_staff',
'is_active', 'date_joined', 'last_login')
In views.py
# -*- coding: utf-8 -*-
from django.http import HttpResponse
from django.views.decorators.csrf import csrf_exempt
from rest_framework.renderers import JSONRenderer
from rest_framework.parsers import JSONParser
from series.models import Serie
from series.serializers import SerieSerializer, UserSerializer
from django.contrib.auth.models import User
from rest_framework import viewsets
def user_list(request):
"""
List all users.
"""
if request.method == 'GET':
usuarios = User.objects.all()
serializer = UserSerializer(usuarios, many=True)
return JSONResponse(serializer.data)
class JSONResponse(HttpResponse):
"""
An HttpResponse that renders its content into JSON.
"""
def __init__(self, data, **kwargs):
content = JSONRenderer().render(data)
kwargs['content_type'] = 'application/json'
super(JSONResponse, self).__init__(content, **kwargs)
===============================================
Serializando el model user de django usando CBV
===============================================
En las urls.py de alguna app
# -*- coding: utf-8 -*-
from django.conf.urls import *
from django.contrib import admin
from series import views
urlpatterns = [
url(r'^$', views.index, name='index'),
url(r'^users/$', views.UsersList.as_view()),
url(r'^users/(?P<pk>[0-9]+)/$', views.UserDetail.as_view()),
]
In serializer.py
# -*- coding: utf-8 -*-
from rest_framework import serializers
from django.contrib.auth.models import User
class UserSerializer(serializers.HyperlinkedModelSerializer):
class Meta:
model = User
fields = ('id', 'username', 'email', 'first_name', 'last_name', 'is_superuser', 'is_staff',
'is_active', 'date_joined', 'last_login')
In views.py
# -*- coding: utf-8 -*-
from django.http import HttpResponse
from django.views.decorators.csrf import csrf_exempt
from rest_framework.renderers import JSONRenderer
from rest_framework.parsers import JSONParser
from series.serializers import UserSerializer
from django.contrib.auth.models import User
from rest_framework import viewsets
from django.http import Http404
from rest_framework.views import APIView
from rest_framework.response import Response
from rest_framework import status
def index(request):
"""
Index view, to tray.
"""
return HttpResponse("Hello, world!")
class JSONResponse(HttpResponse):
"""
An HttpResponse that renders its content into JSON.
"""
def __init__(self, data, **kwargs):
content = JSONRenderer().render(data)
kwargs['content_type'] = 'application/json'
super(JSONResponse, self).__init__(content, **kwargs)
class UsersList(APIView):
"""
List all Users
"""
def get(self, request, format=None):
usuarios = User.objects.all()
serializer = UserSerializer(usuarios, many=True)
return Response(serializer.data)
class UserDetail(APIView):
"""
Retrieve, update or delete a user instance.
"""
def get_object(self, pk):
try:
return User.objects.get(pk=pk)
except User.DoesNotExist:
raise Http404
def get(self, request, pk, format=None):
usuario = self.get_object(pk)
serializer = UserSerializer(usuario)
return Response(serializer.data)
def put(self, request, pk, format=None):
usuario = self.get_object(pk)
serializer = UserSerializer(usuario, data=request.data)
if serializer.is_valid():
serializer.save()
return Response(serializer.data)
return Response(serializer.errors, status=status.HTTP_400_BAD_REQUEST)
def delete(self, request, pk, format=None):
usuario = self.get_object(pk)
usuario.delete()
return Response(status=status.HTTP_204_NO_CONTENT)
===========================
Utilizando ModelSerializers
===========================
De la misma manera que Django ofrece las clases Form y ModelForm, REST framework
incluye las clases Serializer y ModelSerializer para trabajar los modelos.
# -*- coding: utf-8 -*-
from django.forms import widgets
from rest_framework import serializers
from snippets.models import Snippet
In serializer.py
class SnippetSerializer(serializers.ModelSerializer):
"""
Utilizando ModelSerializers para mostrar la data
"""
class Meta:
model = Snippet
fields = ('id', 'title', 'code', 'language')
class SnippetSerializer(serializers.Serializer):
"""
Utilizando Serializers para mostrar la data
"""
pk = serializers.IntegerField(read_only=True)
title = serializers.CharField(required=False, allow_blank=True, max_length=100)
code = serializers.CharField(style={'base_template': 'textarea.html'})
language = serializers.CharField(required=False, allow_blank=True, max_length=50)
===========================
Paginar la lista de objetos
===========================
Las vistas de listas de usuarios u otros modelos podrían terminar devolviendo un
montón de instancias, así que es conveniente paginar los resultados, esto
permite que el cliente API pase por cada una de las página individuales.
Variable de paginación en settings.py
REST_FRAMEWORK = {
'DEFAULT_PERMISSION_CLASSES': [
'rest_framework.permissions.IsAdminUser',
],
'PAGE_SIZE': 5
}
=====================
Permisos del API-Rest
=====================
REST_FRAMEWORK = {
'DEFAULT_PERMISSION_CLASSES': [
'rest_framework.permissions.IsAdminUser',
],
}
class EntidadViewSet(viewsets.ModelViewSet):
"""!
Clase que gestiona los datos rest de las Entidades
"""
queryset = Entidad.objects.all()
serializer_class = EntidadSerializer
# Si no se pasa esta variable todos los métodos están disponibles
# En este ejemplo solo habilitamos la visualización de datos por get
http_method_names = ['get','head']
=================
Probando Api-rest
=================
Si tenemos un api configurada, con permisos de usuario establecidos, podemos
hacer una consulta a los datos pasandole el usuario y la contraseña además de la
url que queremos consultar, usando curl serían de la siguiente manera.
$ curl -H 'Accept: application/json; indent=4' -u username_admin:password123 http://127.0.0.1:8000/users/
api/municipio?parroquia=123
api/parroquia?municipio=12415
===================
Usando DjangoFilter
===================
Instalamos Django Filter
$ pip install django-filter
Agregamos el paquete a las aplicaciones instaladas
INSTALLED_APPS = [
.
.
.
'django_filters',
'app_name',
]
Agregamos lo siguiente al settings.py
REST_FRAMEWORK = {
'DEFAULT_FILTER_BACKENDS': ('django_filters.rest_framework.DjangoFilterBackend',)
}
Ejemplo de urls para ver los usuarios de Django
urlpatterns = [
url(r'^users/$', views.UsersList.as_view()),
url(r'^users/(?P<pk>[0-9]+)/$', views.UserDetail.as_view()),
]
Usando las bondades de Django Filter en los views.py
class UsersList(generics.ListAPIView):
"""!
Clase que permite listar los datos rest de los usuarios
"""
queryset = User.objects.all()
serializer_class = UserSerializer
filter_fields = ('id', 'username', 'email',)
Si visitamos nuestra API Rest se debe haber activado una opción Filter o Filtros
junto a los botones azules de OPTIONS y GET que nos permitirá filtrar a traves
de un formulario y obtener urls como la siguiente:
http://192.168.12.148:8000/users/?id=1
===============================
Leyendo un query en el template
===============================
views.py
class Index(TemplateView):
template_name = "index.html"
def get(self,request,*args, **kwargs):
data = User.objects.all().order_by('-date_joined')
return render(request,self.template_name, {'data':data})
index.html
<table border="1px" width="100%" cellspacing="0">
<thead>
<tr>
<th>ID</th>
<th>Username</th>
<th>Email</th>
</tr>
</thead>
<tbody>
{% for x in data %}
<tr>
<td>{{ x.id }}</td>
<td>{{ x.username }}</td>
<td>{{ x.email }}</td>
</tr>
{% endfor %}
</tbody>
</table>
=========================================
Así se ve el json de la lista de usuarios
=========================================
[{"id":2,"username":"aosorio","email":"[email protected]"},{"id":1,"username":"admin","email":"[email protected]"}]