Django Rest Framework
Tutorial. Cómo crear una API con Django Rest Framework
In computer programming, an application programming interface (API) is a set of subroutine definitions, protocols, and tools for building application software. In general terms, it is a set of clearly defined methods of communication between various software components. A good API makes it easier to develop a computer program by providing all the building blocks, which are then put together by the programmer.
El desarrollo de API's se ha convertido en los últimos años en una parte fundamental de la web. Con la aparición de nuevos dispositivos, la necesidad de tener estandarizada y centralizada la forma en la que se consume información, se ha hecho más importante que nunca.
En mi trabajo he tenido la oportunidad de diseñar e implementar una API con Django Rest Framework ha sido una experiencia muy satisfactoria.
En esta ocasión, además de hacer un post explicando cómo montar una API con Django Rest Framework, tambien teneis disponible un pequeño videotutorial.
Herramientas
Las herramientas que vamos a necesitar son las siguientes:
Docker, para poder tener la API totalmente aislada y dentro de un contenedor, la terminal, para lanzar todos los comandos necesarios y PyCharm, que lo vamos a usar como IDE de programación.
Estructura y configuración
Para poder empezar a desarrollar la API necesitamos configurar el proyecto de la siguiente forma:
$ docker-compose run --rm djangorest django-admin.py startproject drf_basics .
Esto generará un proyecto Django llamado 'drf_basics'.
$ docker-compose run --rm djangorest python manage.py startapp superheroes
Posteriormente procedemos a la generación de ficheros para la aplicación, como en este caso va a ser una API de superheroes, lo hemos llamado 'superheroes'.
Después de ejecutar estos comandos, el directorio tendrá el siguiente aspecto:
⇒ ls Dockerfile docker-compose.yml drf_basics manage.py requirements.txt superheroes
Se puede ver que hay 2 ficheros relacionados con Docker, no los voy a explicar por ser no ser la temática específica del post, pero contienen las definiciones necesarias para que la API pueda funcionar dentro de un contenedor.
Siempre podéis echarle un vistazo a este post sobre funcionamiento de Docker y docker-compose, en el cual hablo ampliamente de estos componentes.
El fichero de 'requirments.txt' es un fichero que contiene la paquetería python necesaria para que el proyecto pueda funcionar. Los únicos paquetes que necesita la API son 'django' y el propio 'djangorestframework'.
django djangorestframework
Configuración del proyecto
Dentro del directorio 'drf_basics/settings.py' tenemos que agregar las siguientes líneas en la sección 'INSTALLED_APPS' para que el proyecto Django sepa qué módulos estamos usando:
'rest_framework', 'superheroes.apps.SuperheroesConfig'
'INSTALLED_APPS' quedaría de esta forma:
INSTALLED_APPS = [ 'django.contrib.admin', 'django.contrib.auth', 'django.contrib.contenttypes', 'django.contrib.sessions', 'django.contrib.messages', 'django.contrib.staticfiles', 'rest_framework', 'superheroes.apps.SuperheroesConfig' ]
Modelos
Los modelos mapean tablas de bases de datos en objetos Django. Para crearlos nos vamos al fichero 'models.py' dentro del directorio 'superheroes' y agregamos lo siguiente:
class Publisher(models.Model): name = models.CharField(max_length=100, blank=True, default='') founder = models.CharField(max_length=100, blank=True, default='') class Meta: ordering = ('name',) class SuperHeroe(models.Model): name = models.CharField(max_length=100, blank=True, default='') gender = models.CharField(max_length=100, blank=True, default='') real_name = models.CharField(max_length=100, blank=True, default='') publisher = models.ForeignKey(Publisher) class Meta: ordering = ('name',)
Con esto ya tenemos creados los modelos.
Para generar estos modelos en base de datos tenemos que lanzar los siguientes comandos:
$ docker-compose run --rm djangorest python manage.py makemigrations superheroes
Que generará un fichero de 'migrations' con los modelos. Y posteriormente:
$ docker-compose run --rm djangorest python manage.py migrate
Que aplicará el fichero de migrations a una db sqlite3.
Serializers
Los serializers son la forma que tiene Django Rest de representar y validar los modelos en forma de objetos JSON.
Necesitamos crear un fichero 'serializers.py' dentro del directorio 'superheroes' y agregar las siguientes líneas:
class SuperHeroeSerializer(serializers.ModelSerializer): class Meta: model = SuperHeroe fields = ('id', 'name', 'gender', 'real_name', 'publisher') class PublisherSerializer(serializers.ModelSerializer): class Meta: model = Publisher fields = ('id', 'name', 'founder')
Con esto los serializers estarían listos.
Probando modelos/serializers
Con los modelos y serializers creados podemos ir a la consola de python y agregar los primeros datos a la API.
Para acceder a la consola de python hacemos lo siguiente:
$ docker-compose run --rm djangorest python manage.py shell
Agregamos los primeros modelos de la siguiente forma:
from superheroes.models import Publisher, SuperHeroe from superheroes.serializers import PublisherSerializer, SuperHeroeSerializer marvel = Publisher(name="Marvel Comics", founder="Martin Goodman") marvel.save() hulk = SuperHeroe(name="Hulk", gender="male",real_name="Bruce Banner", publisher=marvel) hulk.save()
Para ver una representación 'JSON' de los modelos basta con llamar a los serializers de la siguiente forma:
serializer = SuperHeroeSerializer(hulk) serializer.data
Bien, nuestra pequeña base de datos de superheroes empieza a tener sus primeros registros :)
Views
Para poder pedir los datos que nos proporciona la combinación de modelos y serializers, necesitamos views.
En el fichero 'superheroes/views.py' agregamos lo siguiente:
from superheroes.models import SuperHeroe, Publisher from superheroes.serializers import SuperHeroeSerializer, PublisherSerializer from rest_framework import generics class SuperHeroeList(generics.ListCreateAPIView): queryset = SuperHeroe.objects.all() serializer_class = SuperHeroeSerializer class SuperHeroeDetail(generics.RetrieveUpdateDestroyAPIView): queryset = SuperHeroe.objects.all() serializer_class = SuperHeroeSerializer class PublisherList(generics.ListCreateAPIView): queryset = Publisher.objects.all() serializer_class = PublisherSerializer class PublisherDetail(generics.RetrieveUpdateDestroyAPIView): queryset = Publisher.objects.all() serializer_class = PublisherSerializer
Para las views usamos las 'mixed-in generic views' de Django Rest Framework, son sencillas y nos permiten cubrir todas las necesidades para la API (GET, POST, UPDATE y DELETE).
Routing
Ha llegado la hora de enlazar todas las partes de la API con el routing, para lograr esto primero nos vamos al fichero 'drf_basics/urls.py' e incluimos las rutas de la app 'superheroes' de la siguiente forma:
url(r'^', include('superheroes.urls')),
El fichero debería quedar así:
from django.conf.urls import url, include from django.contrib import admin urlpatterns = [ url(r'^admin/', admin.site.urls), url(r'^', include('superheroes.urls')), ]
Y en el fichero 'superheores/urls.py':
from django.conf.urls import url, include from rest_framework.urlpatterns import format_suffix_patterns from superheroes import views urlpatterns = [ url(r'^superheroe/$', views.SuperHeroeList.as_view()), url(r'^superheroe/(?P[0-9]+)/$', views.SuperHeroeDetail.as_view()), url(r'^publisher/$', views.PublisherList.as_view()), url(r'^publisher/(?P [0-9]+)/$', views.PublisherDetail.as_view()), ] urlpatterns = format_suffix_patterns(urlpatterns)
Los 'urlpatterns' sirven para que Django Rest Framework pueda encontrar las views asociadas a las expresiones regulares definidas.
Bien! Con esto ya tenemos una API totalmente funcional y lista para ser usada.
Probando la API
Arrancamos la API de la siguiente forma:
$ docker-compose up
Si todo ha ido bien deberíamos poder probar la API en la siguientes URL's:
'http://127.0.0.1:8000/superheroe'
O 'http://127.0.0.1:8000/publisher'
Es muy recomendable explorar las diferentes opciones que da la API navegable de Django Rest Framework.
Si quereis probar los verbos HTTP por terminal, recomiendo la herramienta httpie, para instalarla basta con:
$ pip install httpie
⇒ http --json GET http://127.0.0.1:8000/superheroe/ HTTP/1.0 200 OK Allow: GET, POST, HEAD, OPTIONS Content-Type: application/json Server: WSGIServer/0.1 Python/2.7.13 Vary: Accept, Cookie X-Frame-Options: SAMEORIGIN [ { "gender": "male", "id": 1, "name": "Hulk", "publisher": 1, "real_name": "Bruce Banner" }, { "gender": "male", "id": 2, "name": "Iron Man", "publisher": 1, "real_name": "Tony Stark" } ]
De esta forma podemos probar en la terminal sin tener que recurrir al navegador.
Conclusiones
Es cierto que Django Rest Framework puede parecer al principio un poco complicado, pero a medida que se va ganando soltura esta sensación va desapareciendo.
Siempre podéis echarle un vistazo al proyecto en GitHub y hacer las pruebas que queráis.
Espero que tanto el post como el videotutorial le puedan servir a alguien que quiera iniciarse en Django Rest Framework.
Un saludo.