Continuamos analizando las posibilidades de Django, y su uso con IRIS. En la primera parte de esta serie, mostramos cómo definir modelos y conectarlos con tablas ya existentes en IRIS; en la segunda parte, mostramos un Portal de Administración, con la capacidad de ver qué datos tenemos en esos modelos, con filtros, edición e incluso paginación.
Ahora es el momento de pasar a la acción real - vamos a crear algunas API Rest, en Django, basadas en los mismos datos que usamos antes, del paquete posts-and-tags.
Para hacerlo, usaremos el framework Django REST
El framework Django REST es un potente y flexible kit de herramientas para generar APIs Web.
Algunas razones por las que querrías usar el framework REST:
- La API navegable en la web es una gran ventaja por la facilidad de uso para los desarrolladores
- Políticas de autenticación que incluyen paquetes para OAuth1 y OAuth2
- Serialización que soporta fuentes de datos tanto ORM como no-ORM
- Personalización completa - se pueden usar las habituales vistas basadas en funciones si no se necesitan las funcionalidades más avanzadas
- Extensa documentación y un excelente soporte por parte de la Comunidad
- Utilizado y avalado por empresas reconocidas internacionalmente, como Mozilla, Red Hat, Heroku y Eventbrite
Primero, tenemos que actualizar nuestro archivo requirements.txt con dependencias
# Django itself django>=4.0.0 # InterSystems IRIS driver for Django, and DB-API driver from InterSystems django-iris=>0.1.13 https://raw.githubusercontent.com/intersystems-community/iris-driver-distribution/main/DB-API/intersystems_irispython-3.2.0-py3-none-any.whl # Django REST Framework and its optional dependencies djangorestframework>=3.4.4 # Markdown support for the browsable API. markdown>=3.0.0 # Filtering support django-filter>=1.0.1
E instalarlas
python install -r requirements.txt
Primer borrador de API
Actualizar el fichero urls.py para esto. En este caso indicamos la raíz de nuestra api como api/. De esta manera, cualquier solicitud a http://localhost:8000/api/ se utilizará como raíz para nuestras solicitudes a la API.
from django.contrib import admin
from django.urls import path, include
from rest_framework import routers
router = routers.DefaultRouter()
urlpatterns = [
path('api/', include(router.urls)),
path('admin/', admin.site.urls),
path('api-auth/', include('rest_framework.urls')),
]
PythonPython
El framework Django REST tiene integrada una interfaz de usuario (IU) para la API, cuando el servidor se ejecuta en modo desarrollo con DEBUG=True en settings.py. Y podemos abrir esta URL
Todo está funcionando, ni siquiera tuve que definir nada, solo conecté ese framework a la url. Soporta autorización, para las solicitudes que requieren autorización.
$ curl http://127.0.0.1:8000/api/ {}
Para definir una API para el proyecto, usaremos algunas de las funcionalidades del framework REST como mínimo
- Serializadores - Permiten que datos complejos como conjuntos de consultas e instancias de modelos se conviertan en tipos de datos nativos de Python que pueden representarse fácilmente en
JSON
,XML
u otros tipos de contenido. Los serializadores también proporcionan deserialización, permitiendo que los datos analizados se conviertan de nuevo en tipos complejos, después de validar los datos entrantes. - ViewSet - permite combinar la lógica para un conjunto de vistas relacionadas en una clase única
Vamos a añadir un endpoint para nuestras publicaciones. Muy sencillo, por ahora. Mirad el contenido actualizado de urls.py
from django.contrib import admin
from django.urls import path, include
from rest_framework import routers, serializers, viewsets
from .models import CommunityPost
router = routers.DefaultRouter()
class CommunityPostSerializer(serializers.HyperlinkedModelSerializer):
class Meta:
# class with model
model = CommunityPost
# list of fields to show, or just '__all__'
fields = '__all__'
# ViewSets define the view behavior.
class CommunityPostViewSet(viewsets.ModelViewSet):
queryset = CommunityPost.objects.all()
serializer_class = CommunityPostSerializer
# connect it with API
router.register(r'posts', CommunityPostViewSet)
urlpatterns = [
path('api/', include(router.urls)),
path('admin/', admin.site.urls),
path('api-auth/', include('rest_framework.urls')),
]
PythonPython
Y ahora apareció en la IU web
Solo hay que hacer clic en el enlace aquí, y tendremos la respuesta.
Id hacia abajo, al final, y veréis un formulario generado para nuevos elementos, que se pueden añadir mediante solicitud POST. Todos los campos son adecuados para el tipo de propiedades
En la lista de elementos, se puede hacer clic en la URL de cualquier elemento, y se verá esto. Solo ese elemento en la respuesta y un formulario de edición con una solicitud PUT
Autenticación
Y ya se pueden cambiar los datos, mediante PUT o POST. La necesidad de autorización aún no está activada. El framework REST ofrece varias combinaciones de autenticaciones para su uso, por lo que se pueden abrir algunos de los recursos para un acceso anónimo de solo-lectura. Y autenticarse para poder realizar cambios. O cerrar completamente cualquier acceso. Simplemente configuramos el acceso de solo-lectura para usuarios anónimos y requerimos autenticación para realizar cambios. Para hacerlo, solo hay que añadir estas líneas a settings.py
REST_FRAMEWORK = {
# Use Django's standard `django.contrib.auth` permissions,
# or allow read-only access for unauthenticated users.
'DEFAULT_PERMISSION_CLASSES': [
'rest_framework.permissions.DjangoModelPermissionsOrAnonReadOnly',
],
}
PythonPython
Con esto, no se verá el formulario hasta que se inicie sesión con el nombre de usuario y contraseña para la instancia creada previamente para la Administración de Django.
Paginación
Por defecto, no tiene paginación, pero podemos añadirla fácilmente a cualquier lista. Actualizar la variable REST_FRAMEWORK en settings.py. Configurar la clase de paginación, y el tamaño de página predeterminado
REST_FRAMEWORK = {
...
'DEFAULT_PAGINATION_CLASS': 'rest_framework.pagination.LimitOffsetPagination',
'PAGE_SIZE': 10,
...
}
PythonPython
Como resultado, el JSON resultante cambió ligeramente, añadió elementos relevantes, como los enlaces a las páginas anteriores y siguientes, así como la cantidad total de elementos. Y con la IU se puede navegar a través de las páginas.
Filtrado y Búsqueda
También es bastante sencillo añadir capacidades de filtrado y de búsqueda. Actualizar la variable REST_FRAMEWORK en settings.py.
REST_FRAMEWORK = {
...
'DEFAULT_FILTER_BACKENDS': [
'django_filters.rest_framework.DjangoFilterBackend',
'rest_framework.filters.SearchFilter',
],
...
]
PythonPython
Y actualizar CommunityPostViewSet con una lista de campos para filtrado y para búsqueda
class CommunityPostViewSet(viewsets.ModelViewSet):
queryset = CommunityPost.objects.all()
serializer_class = CommunityPostSerializer
filterset_fields = ['posttype', 'lang', 'published']
search_fields = ['name',]
PythonPython
Y está funcionando directamente desde la IU web
Y al final, tenemos una API Rest completamente funcional, solo para este recurso, por ahora. Bastante sencillo en este momento, pero es posible hacer muchas personalizaciones, conectar otros recursos y enlazarlos.