logo cosasdedevs
Cómo crear una API completa con Django Rest Framework

Cómo crear una API completa con Django Rest Framework



My Profile
Jun 12, 2020

¡Hola! Espero que estéis bien, yo sigo hasta arriba de proyectos y con ganas de seguir mejorando y añadiendo contenido al blog así que esta vez os traigo una serie de tutoriales para aprender a montar una API con Django Rest Framework.

Para aplicar al máximo todo lo que podemos hacer con DRF, vamos a realizar un proyecto que será un CRUD de currículums en el que un usuario podrá registrarse como reclutador o usuario para aparecer en las búsquedas de un reclutador. Ambos podrán autenticarse y el usuario no reclutador podrá añadir información acerca de su experiencia laboral, proyectos realizados, estudios y formación extra académica.

Para la base de datos usaremos PostgreSQL y correremos el proyecto en un contenedor de Docker.

Aunque se añadirán mejoras en el futuro, el tutorial estará dividido en 5 partes.

  1. Creación del proyecto y modelos 👇
  2. Registro y autenticación
  3. Creación, lectura, actualización y borrado de datos
  4. Búsqueda
  5. Unittest

Antes de seguir, si no tienes muy claro el funcionamiento de una API, te dejo esta guía que escribí para entender su funcionamiento al 100%.

Guía para aprender a trabajar con APIs

Bueno, visto todo esto, es hora de ponernos manos a la obra con el proyecto 💪.

Lo primero que haremos será crear el proyecto en el directorio donde lo queramos guardar, esto lo haremos con django-admin. Recordad que necesitaréis tener instalado Django de forma global. Si tenéis dudas con este proceso, mirad este tutorial.

django-admin startproject api_drf_curriculum

Después, en la raíz del proyecto, creamos el archivo requirements.txt con las librerías que usaremos:

django<3
Markdown==3.1.1
django-filter==2.0.0
djangorestframework==3.9.4
psycopg2>=2.7,<3.0
django-ckeditor==5.9.0
Pillow==7.1.2

También necesitaremos crear el archivo .gitignore, ya que este proyecto lo subiremos a un repositorio posteriormente.

.vscode/
*.log
*.pot
*.pyc
.envs
media/

Si vais a seguir el tutorial al 100% utilizando Docker, también crearemos un archivo .dockerignore para que Docker no replique al contenedor ciertos archivos. Creamos el archivo y añadimos el siguiente código.

.envs

Para guardar la información de los accesos a la base de datos, crearemos un directorio llamado .envs y dentro de él, un archivo llamado .postgres.

.envs/.postgres

POSTGRES_DB=curriculum
POSTGRES_USER=alber
POSTGRES_PASSWORD=#T\MzF]qe:z4#tt#
POSTGRES_HOST=db
POSTGRES_PORT=5432

También crearemos otro archivo para guardar el secret key la configuración del modo debug, a este archivo lo llamaremos .django.

.envs/.django

SECRET_KEY=e%ebfx1%5ot@^nqru7!i_705qq7*@30b3-ui5ztoi8$#$p^u1d
DEBUG=1

Para este tutorial vamos a correr el proyecto con Docker, si quieres saber como desplegar un proyecto de Django con Docker, te dejo este tutorial donde lo explico con más detalle.

Aunque en este tutorial voy a mostrar todos los pasos de Docker, si no quieres usar Docker, simplemente instala las librerías con requirements.txt y configura PostgreSQL en tu máquina.

Ahora creamos el archivo Dockerfile y añadimos la configuración de la imagen que lo que hará será crear un directorio llamado code donde irá todo el código de nuestro proyecto, después asignaremos que por defecto el directorio de inicio sea el directorio recién creado /code, después copiamos el archivo requirements.txt, lanzamos la instalación y por último copiamos todo el contenido de nuestro directorio en /code.

FROM python:3
ENV PYTHONUNBUFFERED 1
RUN mkdir /code
WORKDIR /code
COPY requirements.txt /code/
RUN pip install -r requirements.txt
COPY . /code/

Después creamos un archivo llamado docker-compose.yml y añadimos la configuración del proyecto.

version: '3'

services:
  db:
    image: postgres
    env_file:
      - ./.envs/.postgres
    volumes:
      - pgdata:/var/lib/postgresql/data
  web:
    build: .
    command: python manage.py runserver 0.0.0.0:8000
    env_file:
      - ./.envs/.postgres
    volumes:
      - .:/code
    ports:
      - "8000:8000"
    depends_on:
      - db

volumes:
    pgdata:

Con docker-compose, estamos declarando dos servicios, uno para la base de datos y otro para el proyecto en Django además de un volumen llamado pgdata para persistir la información aunque paremos y volvamos a levantar nuestros contenedores.

Si queréis más información acerca de que realiza el docker-compose, aquí lo explico a fondo.

Después construimos el contenedor y lo levantamos.

docker-compose build
docker-compose up -d

Si ahora accedemos a http://localhost:8000 desde nuestro navegador deberíamos ser capaces de ver la página por defecto de Django.

Ahora que ya tenemos nuestro proyecto en funcionamiento vamos a empezar a darle caña.

Para ello, lo primero será añadir rest_framework y ckeditor en INSTALLED_APPS en el archivo api_drf_curriculum/settings.py

INSTALLED_APPS = [
    .
    .
    .
    'rest_framework',
    'ckeditor',
]

Después, en ese mismo archivo, añadimos las conexiones a la base de datos.

DATABASES = {
    'default': {
        'ENGINE': 'django.db.backends.postgresql',
        'NAME': os.environ['POSTGRES_DB'],
        'USER': os.environ['POSTGRES_USER'],
        'PASSWORD': os.environ['POSTGRES_PASSWORD'],
        'HOST': os.environ['POSTGRES_HOST'],
        'PORT': os.environ['POSTGRES_PORT'],
    }
}

También tenemos que añadir las variables de entorno para el secret key y el modo debug:

SECRET_KEY = os.environ['SECRET_KEY']
DEBUG = os.environ['DEBUG']

Por último en settings.py definimos la carpeta donde guardaremos los archivos multimedia, esto lo haremos porque queremos guardar la foto del usuario. Para definir el directorio lo hacemos de esta forma.

MEDIA_ROOT = os.path.join(BASE_DIR, 'media')
MEDIA_URL = '/media/'

Ahora que ya tenemos configurada la base de datos, es hora de crear los modelos.

Empezaremos con el modelo para usuarios, para crearlo, lanzaremos el siguiente comando:

docker exec api_drf_curriculum_web_1 bash -c "python manage.py startapp users"

api_drf_curriculum_web_1 es el nombre del contenedor donde está el proyecto, para ver el nombre del contenedor, deberéis lanzar el comando docker ps y sustituirlo por el que os aparezca a vosotros.

Lo flipante de esto es que aunque lo estamos lanzando en el contenedor, también lo creará en nuestra máquina, vamos que el proyecto en nuestra máquina y en el contenedor están totalmente sincronizados, esa es la magia de Docker 😯

Ahora vamos a crear el modelo para usuarios, para ello utilizaremos el modelo ya existente en Django para usuarios y añadiremos una fecha de modificación, la foto del usuario, teléfono, ciudad, país y la posibilidad de que pueda escribir un extracto de él. A parte, existirá un campo llamado is_recruiter para identificar si el usuario es un reclutador. También modificaremos la configuración por defecto para que el login sea mediante el password en vez de por username.

users/models.py

from django.db import models
from django.contrib.auth.models import AbstractUser
from ckeditor.fields import RichTextField


class User(AbstractUser):
    email = models.EmailField('email address', unique=True)
    USERNAME_FIELD = 'email'
    REQUIRED_FIELDS = ['username']

    modified = models.DateTimeField(auto_now=True)
    photo = models.ImageField(null=True, upload_to='users')
    extract = RichTextField(null=True)
    phone = models.CharField(null=True, max_length=15)
    city = models.CharField(null=True, max_length=255)
    country = models.CharField(null=True, max_length=255)
    is_recruiter = models.BooleanField(default=False)


Una vez creado el modelo, vamos de nuevo a settings.py y añadimos la app users.

INSTALLED_APPS = [
    .
    .
    .
    'rest_framework',
    'ckeditor',
    'users',
]

También añadiremos al final del archivo settings.py AUTH_USER_MODEL = 'users.User' para que utilice nuestro modelo en el proceso de autenticación.

AUTH_USER_MODEL = 'users.User'

Si tenéis dudas sobre este proceso, en este tutorial lo explico con más detalle.

Ahora que ya tenemos el usuario, vamos a crear un super usuario, para ello, primero lanzamos el makemigrations y migrate para crear nuestras tablas en la base de datos.

docker exec api_drf_curriculum_web_1 bash -c "python manage.py makemigrations" 
docker exec api_drf_curriculum_web_1 bash -c "python manage.py migrate" 

Una vez creadas las tablas, tenemos que acceder a nuestro contenedor para crear el super usuario, para ello lanzamos el siguiente comando:

docker exec -ti api_drf_curriculum_web_1 bash

Una vez dentro, lanzamos el comando para crear el usuario:

python manage.py createsuperuser

Una vez creado, salimos del contenedor con exit.

exit

Ahora vamos a crear el resto de apps de nuestro proyecto para posteriormente crear nuestros modelos:

# Experiencia laboral.
docker exec api_drf_curriculum_web_1 bash -c "python manage.py startapp experiences"
# Proyectos
docker exec api_drf_curriculum_web_1 bash -c "python manage.py startapp projects"
# Educación
docker exec api_drf_curriculum_web_1 bash -c "python manage.py startapp education"
# Formación extraacadémica
docker exec api_drf_curriculum_web_1 bash -c "python manage.py startapp extras"

Una vez creadas las apps, vamos a empezar con los modelos, el primero que haremos será el de la experiencia laboral:

experiences/model.py

from django.db import models
from users.models import User

# django-ckeditor
from ckeditor.fields import RichTextField

class Experience(models.Model):
    """Work experience model."""

    user = models.ForeignKey(User, on_delete=models.CASCADE)
    date_ini = models.DateTimeField()
    date_end = models.DateTimeField(null=True)
    company = models.CharField(max_length=255)
    description = RichTextField()


    def __str__(self):
        """Return company and first_name and last_name."""
        return f'{self.user.first_name} {self.user.last_name} | {self.company}'


En este modelo queremos guardar el usuario asociado, la fecha de inicio, la fecha de fin (el campo tiene null=True por si actualmente sigue trabajando ahí), el nombre de la empresa y una descripción del trabajo realizado en la empresa.

projects/model.py

from django.db import models
from users.models import User

# django-ckeditor
from ckeditor.fields import RichTextField

class Project(models.Model):
    """Project model."""

    user = models.ForeignKey(User, on_delete=models.CASCADE)
    date = models.DateTimeField()
    title = models.CharField(max_length=255)
    url = models.URLField(null=True)
    description = RichTextField()


    def __str__(self):
        """Return project title and first_name and last_name."""
        return f'{self.user.first_name} {self.user.last_name} | {self.title}'


Para el modelo de proyectos, guardaremos el usuario asociado, la fecha de creación, un título, la url (si la tiene) y una descripción del proyecto.

education/model.py

from django.db import models
from users.models import User

# django-ckeditor
from ckeditor.fields import RichTextField

class Education(models.Model):
    """Education model."""

    user = models.ForeignKey(User, on_delete=models.CASCADE)
    date_ini = models.DateTimeField()
    date_end = models.DateTimeField(null=True)
    title = models.CharField(max_length=255)


    def __str__(self):
        """Return education and first_name and last_name."""
        return f'{self.user.first_name} {self.user.last_name} | {self.title}'

En el modelo de educación, guardaremos el usuario asociado, fecha de inicio, fecha de finalización (si se ha terminado) y el título.

extras/model.py

from django.db import models
from users.models import User

# django-ckeditor
from ckeditor.fields import RichTextField

class Extra(models.Model):
    """Extra model."""

    user = models.ForeignKey(User, on_delete=models.CASCADE)
    expedition = models.DateTimeField()
    title = models.CharField(max_length=255)
    url = models.URLField(null=True)
    description = RichTextField(null=True)


    def __str__(self):
        """Return extra academic education and first_name and last_name."""
        return f'{self.user.first_name} {self.user.last_name} | {self.title}'

Para la educación extra académica guardaremos el usuario asociado, la fecha de expedición, el título, la url (por si tienes un enlace al título) y una descripción que será opcional.

Con los modelos creados, es hora de añadirlos a INSTALLED_APPS para poder realizar la migración.

INSTALLED_APPS = [
    .
    .
    .
    'rest_framework',
    'ckeditor',
    'users',
    'experiences',
    'projects',
    'education',
    'extras',
]

Y por último lanzamos la migración.

docker exec api_drf_curriculum_web_1 bash -c "python manage.py makemigrations" 
docker exec api_drf_curriculum_web_1 bash -c "python manage.py migrate" 

Con esto ya tendríamos la base de nuestro proyecto, la próxima semana veremos como registrarnos y como realizar el proceso de autenticación.

Espero que este post te ayude y como siempre, te recomiendo seguirme en Twitter para estar al tanto de los nuevo contenido. Ahora también puedes seguirme en Instagram donde estoy subiendo tips, tutoriales en vídeo e información sobre herramientas para developers.

Por último os dejo mi guía para aprender a trabajar con APIs donde explico todo el funcionamiento de una API, el protocolo HTTP y veremos como construir una API con arquitectura REST.

Nos leemos 👋.

19432 vistas

🐍 Sígueme en Twitter

Si te gusta el contenido que subo y no quieres perderte nada, sígueme en Twitter y te avisaré cada vez que cree contenido nuevo 💪
Luego ¡Te sigo!

Nos tomamos en serio tu privacidad

Utilizamos cookies propias y de terceros para recopilar y analizar datos sobre la interacción de los usuarios con cosasdedevs.com. Ver política de cookies.