One place for hosting & domains

      Django

      Cómo instalar el framework web Django en Ubuntu 18.04


      Introducción

      Django es un completo framework web de Python orientado al desarrollo de páginas web y aplicaciones dinámicas. Con Django, puede crear rápidamente aplicaciones web de Python y dejar que el framework realice una buena parte del trabajo pesado.

      A través de esta guía, aprenderá a hacer funcionar Django en un servidor Ubuntu 18.04. Tras la instalación, iniciará un nuevo proyecto para usarlo como base de su sitio.

      Diferentes métodos

      Según sus necesidades y la forma en que desee configurar su entorno de desarrollo, hay diferentes maneras de instalar Django. Ofrecen diferentes ventajas y puede haber un método que se adecue mejor que otros a su situación concreta.

      Entre algunos de estos métodos diferentes se incluyen los siguientes:

      • Instalación general desde paquetes: los repositorios oficiales de Ubuntu contienen paquetes de Django que se pueden instalar con el gestor convencional de paquetes apt. Este método es sencillo, aunque no tan flexible como otros. Además, es posible que la versión que se incluye en los repositorios no esté actualizada como las versiones oficiales disponibles del proyecto.
      • Instalación con pip en un entorno virtual: puede crear un entorno autónomo para sus proyectos utilizando herramientas como venv y virtualenv. Un entorno virtual le permite instalar Django en un directorio de proyecto sin afectar a todo el sistema, junto con otras personalizaciones y paquetes por proyecto. Suele ser el enfoque más práctico y recomendado para trabajar con Django.
      • Instalación de una versión de desarrollo con git: si quiere instalar la última versión de desarrollo en vez de la versión estable, puede adquirir el código en el repositorio de Git. Esto es necesario para acceder a las últimas características y correcciones, y se puede hacer dentro de su entorno virtual. Sin embargo, las versiones de desarrollo no ofrecen las mismas garantías de estabilidad que otras versiones más estables.

      Requisitos previos

      Antes de empezar, debe tener disponible un usuario no root con privilegios sudo en su servidor de Ubuntu 18.04. Para configurarlo, siga nuestra guía de configuración inicial para servidores de Ubuntu 18.04.

      Instalación general desde paquetes

      Si quiere instalar Django usando los repositorios de Ubuntu, el proceso es muy sencillo.

      Primero, actualice su índice de paquete local con apt:

      Luego, verifique la versión de Python que instaló. Ubuntu 18.04 viene con Python 3.6 por defecto. Podrá verificarlo escribiendo lo siguiente:

      Debería ver el siguiente resultado:

      Output

      Python 3.6.5

      A continuación, instale Django:

      • sudo apt install python3-django

      Puede comprobar que la instalación se haya completado de forma correcta escribiendo lo siguiente:

      Output

      1.11.11

      Esto significa que el software se instaló de forma correcta. Posiblemente también observe que la versión de Django no sea estable más reciente. Si desea obtener más información sobre cómo usar el software, continúe para aprender a crear un ejemplo de proyecto.

      Instalación con pip en un entorno virtual

      La forma más flexible de instalar Django en su sistema es hacerlo dentro de un entorno virtual. Le mostraremos cómo instalar Django en un entorno virtual que crearemos con el módulo venv, parte de la biblioteca estándar Python 3. Esta herramienta le permite crear entornos virtuales de Python e instalar paquetes de Python afectar al resto del sistema. De esta manera, puede seleccionar paquetes de Python por proyecto, independientemente de los conflictos con los requisitos de otros proyectos.

      Empecemos actualizando el índice local de paquetes:

      Compruebe la versión de Python que instaló:

      Output

      Python 3.6.5

      A continuación, instale pip desde los repositorios de Ubuntu:

      • sudo apt install python3-pip

      Una vez instalado pip, puede usarlo para instalar el paquete venv:

      • sudo apt install python3-venv

      Ahora, al iniciar un nuevo proyecto puede crear un entorno virtual para él. Empiece creándolo y moviéndolo a un nuevo directorio del proyecto:

      • mkdir ~/newproject
      • cd ~/newproject

      A continuación, cree un entorno virtual dentro del directorio del proyecto usando el comando python que sea compatible con su versión de Python. Llamaremos a nuestro entorno virtual my_env, pero debería asignarle un nombre descriptivo:

      Con esto, se instalarán versiones independientes de Python y pip en una estructura de directorio aislada dentro del directorio de su proyecto. Se creará un directorio que llevará el nombre que seleccione y mantendrá la jerarquía de archivos donde se instalarán sus paquetes.

      Para instalar paquetes en el entorno aislado, debe activarlo escribiendo lo siguiente:

      • source my_env/bin/activate

      Su mensaje debería modificarse para que refleje su presencia actual en su entorno virtual. Tendrá un aspecto parecido al siguiente: (my_env)username@hostname:~/newproject$.

      En su nuevo entorno, puede usar pip para instalar Django. Independientemente de su versión de Python, pip debería llamarse pip cuando esté en su entorno virtual. Tenga en cuenta además que *no *necesita usar sudo porque la instalación se realiza a nivel local:

      Puede verificar la instalación escribiendo lo siguiente:

      Output

      2.1

      Tenga en cuenta que su versión puede diferir de la que se muestra aquí.

      Para salir de su entorno virtual, debe emitir el comando deactivate desde cualquier parte del sistema:

      Debería restablecerse la visualización convencional de su mensaje. Cuando desee trabajar de nuevo en su proyecto, vuelva a activar su entorno virtual regresando al directorio de su proyecto y activando lo siguiente:

      • cd ~/newproject
      • source my_env/bin/activate

      Instalación de la versión de desarrollo con Git

      Si necesita una versión de desarrollo de Django, puede descargarla e instalarla desde su repositorio de Git. Hagámoslo desde un entorno virtual.

      Primero, actualice el índice local de paquetes:

      Compruebe la versión de Python que instaló:

      Output

      Python 3.6.5

      A continuación, instale pip desde los repositorios oficiales:

      • sudo apt install python3-pip

      Instale el paquete venv para crear su entorno virtual:

      • sudo apt install python3-venv

      El siguiente paso es clonar el repositorio de Django. Entre las diferentes versiones, en este repositorio habrá características y correcciones de errores más actualizadas a expensas, posiblemente, de la estabilidad. Puede clonar el repositorio y disponer el duplicado en un directorio llamado ~/django-dev dentro de su directorio de inicio escribiendo lo siguiente:

      • git clone git://github.com/django/django ~/django-dev

      Posiciónese en este directorio:

      Cree un entorno virtual usando el comando python que sea compatible con su versión instalada de Python:

      Actívelo:

      • source my_env/bin/activate

      A continuación, puede instalar el repositorio usando pip. La opción -e se instalará en el modo “editable”, lo cual es necesario al realizar la instalación desde el control de versión:

      • pip install -e ~/django-dev

      Puede comprobar que la instalación se haya realizado de forma correcta escribiendo lo siguiente:

      Output

      2.2.dev20180802155335

      Una vez más, es posible que la versión que vea no coincida con la que se muestra aquí.

      Ahora, contará con la versión más reciente de Django en su entorno virtual.

      Creación de un ejemplo de proyecto

      Con Django instalado, podrá empezar a crear su proyecto. Veremos cómo crear un proyecto y probarlo en su servidor de desarrollo usando un entorno virtual.

      Primero, cree un directorio para su proyecto y posiciónese en él:

      • mkdir ~/django-test
      • cd ~/django-test

      A continuación, cree su entorno virtual:

      Active el entorno:

      • source my_env/bin/activate

      Instale Django:

      Para crear su proyecto, puede usar django-admin con el comando startproject . Llamaremos a nuestro proyecto djangoproject, pero puede usar un nombre diferente. startproject creará dentro de su directorio de trabajo actual un directorio que incluye lo siguiente:

      • Una secuencia de comandos de administración, manage.py, que puede usar para administrar varias tareas específicas de Django.
      • Un directorio (con el mismo nombre que el del proyecto) en el que se incluye el código real del proyecto.

      Sin embargo, para evitar que haya demasiados directorios anidados, indicaremos a Django que disponga la secuencia de comandos de administración y el directorio interno en el directorio actual (véase el punto final):

      • django-admin startproject djangoproject .

      Para migrar la base de datos (este ejemplo utiliza SQLite por defecto), vamos a usar el comando migrate con manage.py. Las migraciones aplican los cambios que ha hecho a sus modelos de Django en su esquema de base de datos.

      Para migrar la base de datos, escriba lo siguiente:

      Verá un resultado como el siguiente:

      Output

      Operations to perform: Apply all migrations: admin, auth, contenttypes, sessions Running migrations: Applying contenttypes.0001_initial... OK Applying auth.0001_initial... OK Applying admin.0001_initial... OK Applying admin.0002_logentry_remove_auto_add... OK Applying admin.0003_logentry_add_action_flag_choices... OK Applying contenttypes.0002_remove_content_type_name... OK Applying auth.0002_alter_permission_name_max_length... OK Applying auth.0003_alter_user_email_max_length... OK Applying auth.0004_alter_user_username_opts... OK Applying auth.0005_alter_user_last_login_null... OK Applying auth.0006_require_contenttypes_0002... OK Applying auth.0007_alter_validators_add_error_messages... OK Applying auth.0008_alter_user_username_max_length... OK Applying auth.0009_alter_user_last_name_max_length... OK Applying sessions.0001_initial... OK

      Por último, vamos a crear un usuario administrativo para que pueda usar la interfaz de administración de Django. Haremos esto con el comando createsuperuser:

      • python manage.py createsuperuser

      Se le solicitará un nombre de usuario, una dirección de correo electrónico y una contraseña para su usuario.

      Modificación de ALLOWED_HOSTS en la configuración de Django

      Para comprobar correctamente su aplicación, deberá modificar una de las directivas en la configuración de Django.

      Abra el archivo de configuración escribiendo lo siguiente:

      • nano ~/django-test/djangoproject/settings.py

      Dentro de este, localice la directiva ALLOWED_HOSTS. Esto define una lista blanca de direcciones o nombres de dominio que pueden utilizarse para la conexión con la instancia de Django. Una solicitud entrante con un encabezado Host que no esté en esta lista generará una excepción. Django necesita que configure esto para evitar una clase de vulnerabilidad de seguridad determinada.

      Dentro de los corchetes, enumere las direcciones IP o los nombres de dominio que estén asociados a su servidor de Django. Cada elemento debería figurar entre comillas, y las entradas deben ir separadas por una coma. Si desea solicitudes de un dominio completo y cualquier subdominio, agregue un período al inicio de la entrada:

      ~/django-test/djangoproject/settings.py

      . . .
      ALLOWED_HOSTS = ['your_server_ip_or_domain', 'your_second_ip_or_domain', . . .]
      

      Cuando termine, guarde el archivo y cierre su editor.

      Comprobación del servidor de desarrollo

      Cuando ya disponga de un usuario, podrá iniciar el servidor de desarrollo de Django para ver el aspecto de un nuevo proyecto de Django. Debería usarlo únicamente para el desarrollo. Cuando esté listo para la implementación, asegúrese de seguir detenidamente las directrices de Django relacionadas con la implementación.

      Antes de probar el servidor de desarrollo, compruebe que abra el puerto correspondiente en su firewall. Si siguió los pasos de la guía de configuración inicial para servidores y usa UFW, puede abrir el puerto 8000 escribiendo lo siguiente:

      Inicie el servidor de desarrollo:

      • python manage.py runserver your_server_ip:8000

      Agregue :8000 al final de la dirección IP de su servidor en su navegador web y visítela:

      http://your_server_ip:8000
      

      Debería ver lo siguiente:

      Página pública de Django

      Para acceder a la interfaz de administrador, añada /admin/ al final de su URL:

      http://your_server_ip:8000/admin/
      

      Con esto, accederá a una pantalla de inicio de sesión:

      Inicio de sesión de administrador en Django

      Si introduce el nombre de usuario y la contraseña de administrador que acaba de crear, tendrá acceso a la sección principal de administración del sitio:

      Página de administración de Django

      Para obtener más información sobre cómo trabajar con la interfaz de administración de Django, consulte “Cómo habilitar y conectar la interfaz de administración de Django”.

      Cuando termine de comprobar el sitio predeterminado, podrá detener el servidor de desarrollo escribiendo CTRL-C en su terminal.

      El proyecto de Django que creó proporciona la base estructural para el diseño de un sitio más completo. Consulte la documentación de Django para obtener más información sobre cómo crear sus aplicaciones y personalizar su sitio.

      Conclusión

      Con esto, habrá instalado Django en su servidor de Ubuntu 18.04 y contará con las principales herramientas que necesita para crear sólidas aplicaciones web. También sabrá iniciar un nuevo proyecto y lanzar el servidor para desarrolladores. El aprovechamiento de un framework web completo como Django puede ayudar a acelerar el desarrollo, lo que le permitirá concentrarse solo en los aspectos únicos de sus aplicaciones.

      Si desea más información sobre cómo trabajar con Django, con acceso a debates en profundidad sobre aspectos como modelos y vistas, consulte nuestra serie de desarrollo de Django.



      Source link

      Cómo configurar Django con Postgres, Nginx y Gunicorn en Ubuntu 18.04


      Introducción

      Django es un poderoso framework que puede ayudarle a poner en marcha su aplicación o sitio web con Python. Incluye un servidor de desarrollo simplificado para probar su código a nivel local. Sin embargo, para cualquier cosa que esté incluso apenas relacionada con la producción se requiere un servidor web más seguro y potente.

      En esta guía, demostraremos la forma de instalar y configurar algunos componentes en Ubuntu 18.04 para que sean compatibles y permitan que funcionen aplicaciones de Django. Configuraremos una base de datos de PostgreSQL en lugar de usar la base de datos predeterminada de SQLite. Configuraremos el servidor de aplicaciones de Gunicorn para que interactúe con nuestras aplicaciones. Luego, configuraremos Nginx para que invierta el proxy de Gunicorn, lo que nos dará acceso a sus funciones de seguridad y rendimiento para nuestras aplicaciones.

      Requisitos previos y objetivos

      Para completar esta guía, debe disponer de una nueva instancia de servidor de Ubuntu 18.04 con un cortafuegos básico y un usuario no root con privilegios sudo configurados. Puede aprender a configurar esto en nuestra guía de configuración inicial para servidores.

      Instalaremos Django en un entorno virtual. Instalar Django en un entorno específico para nuestro proyecto permitirá que sus proyectos y los requisitos de estos se administren por separado.

      Una vez que tengamos nuestra base de datos y la aplicación en funcionamiento, instalaremos y configuraremos el servidor de aplicaciones de Gunicorn. Esto servirá como interfaz para nuestra aplicación, al traducir las solicitudes de los clientes de HTTP a llamadas Python que nuestra aplicación puede procesar. Luego, instalaremos Nginx frente a Gunicorn para aprovechar sus mecanismos de administración de conexiones de alto rendimiento y sus características de seguridad fáciles de implementar.

      Comencemos.

      Instalar los paquetes desde los repositorios de Ubuntu

      Para iniciar este proceso, descargaremos e instalaremos todos los elementos necesarios desde los repositorios de Ubuntu. Usaremos el administrador de paquetes de Python pip para instalar componentes adicionales más tarde.

      Necesitaremos actualizar el índice de paquetes apt local y luego descargaremos e instalaremos los paquetes. Los paquetes que instalemos dependen de la versión de Python que use en su proyecto.

      Si usa Django con Python 3, escriba lo siguiente:

      • sudo apt update
      • sudo apt install python3-pip python3-dev libpq-dev postgresql postgresql-contrib nginx curl

      Django 1.11 es la última versión que será compatible con Python 2. Si inicia nuevos proyectos, le recomendamos totalmente elegir Python 3. Si todavía necesita usar Python 2, escriba lo siguiente:

      • sudo apt update
      • sudo apt install python-pip python-dev libpq-dev postgresql postgresql-contrib nginx curl

      Con esto se instalarán pip, los archivos de desarrollo de Python necesarios para compilar Gunicorn posteriormente, el sistema de base de datos de Postgres, las bibliotecas necesarias para la interacción con él, y el servidor web de Nginx.

      Crear la base de datos y el usuario de PostgreSQL

      Crearemos una base de datos y un usuario de base de datos para nuestra aplicación de Django.

      Por defecto, Postgres usa un esquema de autenticación llamado “autenticación por pares” para las conexiones locales. Básicamente, esto significa que si el nombre de usuario del sistema operativo del usuario coincide con un nombre de usuario de Postgres válido, ese usuario puede iniciar sesión sin autenticaciones adicionales.

      Durante la instalación de Postgres, se creó un usuario del sistema operativo llamado postgres para que se corresponda con el usuario administrativo postgres de PostgreSQL. Necesitamos usar este usuario para realizar tareas administrativas. Podemos usar sudo y pasar el nombre de usuario con la opción -u.

      Inicie una sesión interactiva de Postgres escribiendo lo siguiente:

      Recibirá un mensaje de PostgreSQL en el que se pueden configurar los requisitos.

      Primero, cree una base de datos para su proyecto:

      • CREATE DATABASE myproject;

      Nota: Cada instrucción de Postgres debe terminar con un punto y coma. Por ello, si está experimenta problemas debe asegurarse de que su comando tenga esta terminación.

      A continuación, cree un usuario de base de datos para nuestro proyecto. Asegúrese de elegir una contraseña segura.

      • CREATE USER myprojectuser WITH PASSWORD 'password';

      Más adelante, modificaremos algunos de los parámetros de conexión para el usuario que acabamos de crear. Esto acelerará las operaciones de la base de datos para que no sea necesario consultar y fijar los valores correctos cada vez que se establezca una conexión.

      Fijaremos el código predeterminado en UTF-8, lo que se prevé para Django. También fijaremos el esquema predeterminado de aislamiento de transacciones en “read committed”, que bloquea las lecturas de transacciones no comprometidas. Por último, configuraremos la zona horaria. Por defecto, nuestros proyectos de Django se configurarán para usar la opción UTC. Estas son todas las recomendaciones del propio proyecto de Django:

      • ALTER ROLE myprojectuser SET client_encoding TO 'utf8';
      • ALTER ROLE myprojectuser SET default_transaction_isolation TO 'read committed';
      • ALTER ROLE myprojectuser SET timezone TO 'UTC';

      Ahora, podemos brindar a nuestro nuevo usuario acceso para administrar nuestra nueva base de datos:

      • GRANT ALL PRIVILEGES ON DATABASE myproject TO myprojectuser;

      Cuando termine, cierre la línea de comandos de PostgreSQL escribiendo lo siguiente:

      Postgres quedará, así, configurado para que Django pueda conectarse y administrar la información de su base de datos.

      Crear un entorno virtual de Python para su proyecto

      Ahora que tenemos nuestra base de datos, podemos empezar a cumplir con el resto de los requisitos de nuestro proyecto. Instalaremos los componentes de Python requeridos en un entorno virtual para facilitar la administración.

      Para hacerlo, primero necesitamos acceso al comando virtualenv. Podemos instalarlo con pip.

      Si usa Python 3, actualice pip e instale el paquete escribiendo lo siguiente:

      • sudo -H pip3 install --upgrade pip
      • sudo -H pip3 install virtualenv

      Si usa** Python 2**, actualice pip e instale el paquete escribiendo lo siguiente:

      • sudo -H pip install --upgrade pip
      • sudo -H pip install virtualenv

      Con virtualenv instalado, podemos comenzar a dar forma a nuestro proyecto. Cree y un directorio en el que podamos guardar los archivos de nuestro proyecto y posiciónese en él:

      • mkdir ~/myprojectdir
      • cd ~/myprojectdir

      En el directorio del proyecto, cree un entorno virtual de Python escribiendo lo siguiente:

      Con esto, se creará un directorio llamado myprojectenv en su directorio myprojectdir. De forma interna, instalará una versión local de Python y una versión local de pip. Podemos usar esto para instalar y configurar un entorno aislado de Python para nuestro proyecto.“”“

      Antes de instalar los componentes de Python requeridos para nuestro proyecto, debemos activar el entorno virtual. Puede hacerlo escribiendo lo siguiente:

      • source myprojectenv/bin/activate

      Su línea de comandos cambiará para indicar que ahora realiza operaciones en un entorno virtual de Python. Tendrá un aspecto parecido a este: (myprojectenv)user@host:~/myprojectdir$.”

      Con su entorno virtual activo, instale Django, Gunicorn y el adaptador psycopg2 de PostgreSQL con la instancia local de pip:

      Nota: Cuando se active el entorno virtual (cuando (myprojectenv) se encuentre al inicio de su línea de comandos), use pip en lugar de pip3, incluso si emplea Python 3. La copia del entorno virtual de la herramienta siempre se llama pip, independientemente de la versión de Python.

      • pip install django gunicorn psycopg2-binary

      Con esto, debería contar con todo el software necesario para iniciar un proyecto en Django.

      Crear y configurar un nuevo proyecto de Django

      Una vez instalados nuestros componentes de Python, podemos crear los archivos reales del proyecto en Django.

      Crear el proyecto de Django

      Debido a que ya disponemos de un directorio de proyectos, le indicaremos a Django que instale los archivos en él. Se creará un directorio de segundo nivel con el código real, lo cual es normal, y se dispondrá una secuencia de comandos de administración en este directorio. La clave para esto es que definiremos el directorio de forma explícita en lugar de permitir que Django tome decisiones vinculadas con nuestro directorio actual:

      • django-admin.py startproject myproject ~/myprojectdir

      En este punto, el directorio de su proyecto (~/myprojectdir en nuestro caso) debe tener el siguiente contenido:“

      • ~/myprojectdir/manage.py: secuencia de comandos de administración del proyecto en Django.
      • ~/myprojectdir/myproject/: paquete de proyectos de Django. Este debería contener los archivos __init__.py, settings.py, urls.py y wsgi.py.
      • ~/myprojectdir/myprojectenv/: directorio del entorno virtual que creamos antes.

      Ajustar la configuración del proyecto

      Lo primero que debemos hacer con los archivos del proyecto recientemente creado es ajustar la configuración. Abra el archivo de configuración en su editor de texto:

      • nano ~/myprojectdir/myproject/settings.py

      Localice primero la directiva ALLOWED_HOSTS. Con esto, se define una lista de las direcciones de los servidores o los nombres de dominio que pueden usarse para establecer una conexión con la instancia en Django. Cualquier solicitud entrante con un encabezado de Host que no figure en esta lista generará una excepción. Django necesita que configure esto para evitar una clase de vulnerabilidad de seguridad determinada.

      Dentro de los corchetes, enumere las direcciones IP o los nombres de dominio asociados a su servidor de Django. Cada elemento debe listarse entre comillas y las entradas deben ir separadas por una coma. Si desea solicitudes para un dominio completo y cualquier subdominio, anteponga un punto al comienzo de la entrada. En el fragmento inferior, hay algunos ejemplos comentados que se usan para demostrar lo siguiente:

      Nota: Asegúrese de incluir localhost como una de las opciones, ya que autorizaremos conexiones a través de una instancia local de Nginx.

      ~/myprojectdir/myproject/settings.py

      . . .
      # The simplest case: just add the domain name(s) and IP addresses of your Django server
      # ALLOWED_HOSTS = [ 'example.com', '203.0.113.5']
      # To respond to 'example.com' and any subdomains, start the domain with a dot
      # ALLOWED_HOSTS = ['.example.com', '203.0.113.5']
      ALLOWED_HOSTS = ['your_server_domain_or_IP', 'second_domain_or_IP', . . ., 'localhost']
      

      A continuación, busque la sección que configura el acceso a la base de datos. Se iniciará con DATABASES. La configuración del archivo es para una base de datos de SQLite. Ya creamos una base de datos de PostgreSQL para nuestro proyecto. Ahora debemos ajustar las configuraciones.

      Cambie las configuraciones por la información de su base de datos de PostgreSQL. Indicaremos a Django que use el adaptador psycopg2 que instalamos con pip. Debemos proporcionar el nombre de la base de datos, el nombre de usuario y la contraseña del usuario, y luego especificar que la base de datos se encuentra en una computadora local. Puede dejar la configuración de PORT como una secuencia de comandos vacía:

      ~/myprojectdir/myproject/settings.py

      . . .
      
      DATABASES = {
          'default': {
              'ENGINE': 'django.db.backends.postgresql_psycopg2',
              'NAME': 'myproject',
              'USER': 'myprojectuser',
              'PASSWORD': 'password',
              'HOST': 'localhost',
              'PORT': '',
          }
      }
      
      . . .
      

      A continuación, diríjase hasta la parte inferior del archivo y agregue una configuración que indique dónde deben disponerse los archivos estáticos. Esto es necesario para que Nginx pueda manejar las solicitudes de estos elementos. La siguiente línea indica a Django que los disponga en un directorio llamado static en el directorio de proyectos de base:

      ~/myprojectdir/myproject/settings.py

      . . .
      
      STATIC_URL = '/static/'
      STATIC_ROOT = os.path.join(BASE_DIR, 'static/')
      

      Guarde y cierre el archivo cuando termine.

      Completar la configuración inicial del proyecto

      Ahora, podemos migrar el esquema inicial de la base de datos a nuestra base de datos de PostgreSQL usando la secuencia de comandos de administración:

      • ~/myprojectdir/manage.py makemigrations
      • ~/myprojectdir/manage.py migrate

      Cree un usuario administrativo para el proyecto escribiendo lo siguiente:

      • ~/myprojectdir/manage.py createsuperuser

      Deberá seleccionar el nombre de usuario, proporcionar una dirección de correo electrónico y elegir y confirmar una contraseña.

      Podemos recolectar todo el contenido estático en la ubicación del directorio que configuramos escribiendo lo siguiente:

      • ~/myprojectdir/manage.py collectstatic

      Deberá confirmar la operación. Luego, los archivos estáticos se ubicarán en un directorio llamado static, dentro del directorio de su proyecto.

      Si siguió la guía de configuración inicial para servidores, debería proteger su servidor con un firewall UFW. Para probar el servidor de desarrollo, tendremos que permitir el acceso al puerto que usaremos.

      Cree una excepción para el puerto 8000 escribiendo lo siguiente:

      Por último, puede probar su proyecto iniciando el servidor de desarrollo de Django con este comando:

      • ~/myprojectdir/manage.py runserver 0.0.0.0:8000

      En su buscador web, agregue :8000 al final del nombre del dominio o de la dirección IP de su servidor y visítelos:

      http://server_domain_or_IP:8000
      

      Debería ver la página de índice predeterminada de Django:

      Página de índice de Django

      Si agrega /admin al final de la URL en la barra de direcciones, se le solicitará el nombre de usuario administrativo y la contraseña que creó con el comando createsuperuser:

      Inicio de sesión de administrador de Django

      Después de la autenticación, puede acceder a la interfaz administrativa predeterminada de Django:

      Interfaz de administración de Django

      Cuando finalice la exploración, presione *CTRL-C *en la ventana de la terminal para desactivar el servidor de desarrollo.

      Poner a prueba la capacidad de Gunicorn para presentar el proyecto

      Lo último que nos convendrá hacer antes de cerrar nuestro entorno virtual será probar Gunicorn para asegurarnos de que pueda hacer funcionar la aplicación. Podemos hacerlo ingresando a nuestro directorio de proyectos y usando gunicorn para cargar el módulo WSGI del proyecto:

      • cd ~/myprojectdir
      • gunicorn --bind 0.0.0.0:8000 myproject.wsgi

      Con esto se iniciará Gunicorn en la misma interfaz en la que se encontraba en ejecución el servidor de desarrollo en Django. Puede volver y probar la aplicación de nuevo.

      Nota: No se aplicará el estilo a la interfaz de administración, ya que Gunicorn no tiene forma de encontrar el contenido estático de CSS responsable de este.

      Pasamos a Gunicorn un módulo especificando la ruta relativa del directorio al archivo wsgi.py de Django, que es el punto de entrada a nuestra aplicación, usando la sintaxis del módulo de Python. Dentro de este archivo, se define una función llamada application, que se usa para comunicarse con la aplicación. Para obtener más información sobre la especificación de WSGI, haga clic aquí.

      Cuando termine de realizar las pruebas, presione CTRL-C en la ventana de la terminal para detener Gunicorn.

      Con esto habremos terminado de configurar nuestra aplicación en Django. Podemos cerrar nuestro entorno virtual escribiendo lo siguiente:

      Se eliminará el indicador del entorno virtual en su línea de comandos.

      Crear archivos de socket y servicio de systemd para Gunicorn

      Comprobamos que Gunicorn puede interactuar con nuestra aplicación en Django, pero debemos implementar un mejor método para iniciar y detener el servidor de la aplicación. Para lograr esto, crearemos archivos de servicio y socket systemd.

      El socket Gunicorn se creará en el inicio y escuchará las conexiones. Cuando se establezca una conexión, systemd iniciará de forma automática el proceso de Gunicorn para manejarla conexión.

      Comience creando y abriendo un archivo de socket de systemd para Gunicorn con privilegios sudo:

      • sudo nano /etc/systemd/system/gunicorn.socket

      Dentro de él, crearemos una sección [Unit] para describir el socket, una sección [Socket] para definir la ubicación del socket y una sección [Install] para asegurarnos de que el socket se cree en el momento adecuado:

      /etc/systemd/system/gunicorn.socket

      [Unit]
      Description=gunicorn socket
      
      [Socket]
      ListenStream=/run/gunicorn.sock
      
      [Install]
      WantedBy=sockets.target
      

      Guarde y cierre el archivo cuando termine.

      A continuación, cree y abra un archivo de servicio systemd para Gunicorn con privilegios sudo en su editor de texto. El nombre del archivo de servicio debe coincidir con el de socket, salvo en la extensión:

      • sudo nano /etc/systemd/system/gunicorn.service

      Empiece por la sección [Unit], que se usa para especificar metadatos y dependencias. Aquí introduciremos una descripción de nuestro servicio e indicaremos al sistema init que lo inicie solo tras haber alcanzado el objetivo de red: Debido a que nuestro servicio se basa en el socket del archivo de sockets, necesitamos incluir una directiva Requires para indicar esta relación:

      /etc/systemd/system/gunicorn.service

      [Unit]
      Description=gunicorn daemon
      Requires=gunicorn.socket
      After=network.target
      

      A continuación, abriremos la sección [Service]. Especificaremos el usuario y el grupo con los cuales deseamos que se ejecute el proceso. Otorgaremos la propiedad del proceso a nuestra cuenta de usuario normal, ya que tiene la propiedad de todos los archivos pertinentes. Otorgaremos la propiedad del grupo al grupo www-data para que Nginx pueda comunicarse fácilmente con Gunicorn.

      Luego, mapearemos el directorio de trabajo y especificaremos el comando que se usará para iniciar el servicio. En este caso, tendremos que especificar la ruta completa al ejecutable de Gunicorn, que está instalado en nuestro entorno virtual. Vincularemos el proceso con el socket de Unix que creamos en el directorio /run para que el proceso pueda comunicarse con Nginx. Registramos todos los datos a la salida estándar para que el proceso journald pueda recopilar los registros de Gunicorn. También podemos especificar cualquier ajuste opcional de Gunicorn aquí. Por ejemplo, especificamos 3 procesos de trabajadores en este caso:

      /etc/systemd/system/gunicorn.service

      [Unit]
      Description=gunicorn daemon
      Requires=gunicorn.socket
      After=network.target
      
      [Service]
      User=sammy
      Group=www-data
      WorkingDirectory=/home/sammy/myprojectdir
      ExecStart=/home/sammy/myprojectdir/myprojectenv/bin/gunicorn 
                --access-logfile - 
                --workers 3 
                --bind unix:/run/gunicorn.sock 
                myproject.wsgi:application
      

      Por último, agregaremos una sección [Install]. Esto indicará a systemd a qué deberá vincular este servicio si lo habilitamos para que se cargue en el inicio. Queremos que este servicio se inicie cuando el sistema multiusuario normal esté en funcionamiento:

      /etc/systemd/system/gunicorn.service

      [Unit]
      Description=gunicorn daemon
      Requires=gunicorn.socket
      After=network.target
      
      [Service]
      User=sammy
      Group=www-data
      WorkingDirectory=/home/sammy/myprojectdir
      ExecStart=/home/sammy/myprojectdir/myprojectenv/bin/gunicorn 
                --access-logfile - 
                --workers 3 
                --bind unix:/run/gunicorn.sock 
                myproject.wsgi:application
      
      [Install]
      WantedBy=multi-user.target
      

      Con eso, nuestro archivo de servicio de systemd quedará completo. Guárdelo y ciérrelo ahora.

      Ahora podemos iniciar y habilitar el socket de Gunicorn. Con esto se creará el archivo de socket en /run/gunicorn.sock ahora y en el inicio. Cuando se establezca una conexión con ese socket, systemd iniciará gunicorn.service de forma automática para gestionarla:

      • sudo systemctl start gunicorn.socket
      • sudo systemctl enable gunicorn.socket

      Podemos confirmar que la operación se haya completado con éxito revisando el archivo de sockets.

      Verificar el archivo de socket de Gunicorn

      Compruebe el estado del proceso para saber si pudo iniciar lo siguiente:

      • sudo systemctl status gunicorn.socket

      A continuación, compruebe la existencia del archivo gunicorn.sock en el directorio /run:

      Output

      /run/gunicorn.sock: socket

      Si el comando systemctl status indica que se produjo un error o si no encuentra el archivo gunicorn.sock en el directorio, significa que no se pudo crear de forma correcta el socket de Gunicorn. Verifique los registros del socket de Gunicorn escribiendo lo siguiente:

      • sudo journalctl -u gunicorn.socket

      Vuelva a revisar su archivo /etc/systemd/system/gunicorn.socket para solucionar cualquier problema antes de continuar.

      Poner a prueba la activación de sockets

      En este punto, si solo inició la unidad gunicorn.socket, gunicorn.service aún no estará activo, ya que el socket aún no habrá recibido conexiones. Puede comprobarlo escribiendo lo siguiente:

      • sudo systemctl status gunicorn

      Output

      ● gunicorn.service - gunicorn daemon Loaded: loaded (/etc/systemd/system/gunicorn.service; disabled; vendor preset: enabled) Active: inactive (dead)

      Para probar el mecanismo de activación de sockets, podemos enviar una conexión al socket a través de curl escribiendo lo siguiente:

      • curl --unix-socket /run/gunicorn.sock localhost

      Debería ver el resultado HTML de su aplicación en la terminal. Esto indica que Gunicorn se inició y pudo presentar su aplicación de Django. Puede verificar que el servicio de Gunicorn funcione escribiendo lo siguiente:

      • sudo systemctl status gunicorn

      Output

      ● gunicorn.service - gunicorn daemon Loaded: loaded (/etc/systemd/system/gunicorn.service; disabled; vendor preset: enabled) Active: active (running) since Mon 2018-07-09 20:00:40 UTC; 4s ago Main PID: 1157 (gunicorn) Tasks: 4 (limit: 1153) CGroup: /system.slice/gunicorn.service ├─1157 /home/sammy/myprojectdir/myprojectenv/bin/python3 /home/sammy/myprojectdir/myprojectenv/bin/gunicorn --access-logfile - --workers 3 --bind unix:/run/gunicorn.sock myproject.wsgi:application ├─1178 /home/sammy/myprojectdir/myprojectenv/bin/python3 /home/sammy/myprojectdir/myprojectenv/bin/gunicorn --access-logfile - --workers 3 --bind unix:/run/gunicorn.sock myproject.wsgi:application ├─1180 /home/sammy/myprojectdir/myprojectenv/bin/python3 /home/sammy/myprojectdir/myprojectenv/bin/gunicorn --access-logfile - --workers 3 --bind unix:/run/gunicorn.sock myproject.wsgi:application └─1181 /home/sammy/myprojectdir/myprojectenv/bin/python3 /home/sammy/myprojectdir/myprojectenv/bin/gunicorn --access-logfile - --workers 3 --bind unix:/run/gunicorn.sock myproject.wsgi:application Jul 09 20:00:40 django1 systemd[1]: Started gunicorn daemon. Jul 09 20:00:40 django1 gunicorn[1157]: [2018-07-09 20:00:40 +0000] [1157] [INFO] Starting gunicorn 19.9.0 Jul 09 20:00:40 django1 gunicorn[1157]: [2018-07-09 20:00:40 +0000] [1157] [INFO] Listening at: unix:/run/gunicorn.sock (1157) Jul 09 20:00:40 django1 gunicorn[1157]: [2018-07-09 20:00:40 +0000] [1157] [INFO] Using worker: sync Jul 09 20:00:40 django1 gunicorn[1157]: [2018-07-09 20:00:40 +0000] [1178] [INFO] Booting worker with pid: 1178 Jul 09 20:00:40 django1 gunicorn[1157]: [2018-07-09 20:00:40 +0000] [1180] [INFO] Booting worker with pid: 1180 Jul 09 20:00:40 django1 gunicorn[1157]: [2018-07-09 20:00:40 +0000] [1181] [INFO] Booting worker with pid: 1181 Jul 09 20:00:41 django1 gunicorn[1157]: - - [09/Jul/2018:20:00:41 +0000] "GET / HTTP/1.1" 200 16348 "-" "curl/7.58.0"

      Si el resultado de curl o systemctl status indica que se produjo un problema, verifique los registros para obtener información adicional:

      • sudo journalctl -u gunicorn

      Verifique su archivo /etc/systemd/systemd/system/gunicorn.service en busca de problemas. Si realiza cambios en el archivo /etc/systemd/systemd/system/gunicorn.service, vuelva a cargar el demonio para volver a leer la definición de servicio y reiniciar el proceso de Gunicorn escribiendo lo siguiente:

      • sudo systemctl daemon-reload
      • sudo systemctl restart gunicorn

      Asegúrese de resolver los problemas mencionados previamente antes de continuar.

      Configurar Nginx para un pase de autorización a Gunicorn

      Ahora que Gunicorn está configurado, debemos configurar Nginx para transferir tráfico al proceso.

      Comience creando y abriendo un nuevo bloque de servidor en el directorio sites-available de Nginx:

      • sudo nano /etc/nginx/sites-available/myproject

      Dentro de este, abra un nuevo bloque de servidor. Comenzaremos especificando que este bloque debe escuchar en el puerto normal 80 y responder al nombre de dominio o a la dirección IP de nuestro servidor:

      /etc/nginx/sites-available/myproject

      server {
          listen 80;
          server_name server_domain_or_IP;
      }
      

      A continuación, indicaremos a Nginx que ignore cualquier problema para encontrar un favicon. También le indicaremos dónde encontrar los activos estáticos que recolectamos en nuestro directorio ~/myprojectdir/static. Todos estos archivos tienen un prefijo URI de “/static”, para que podamos crear un bloque de ubicación que coincida con estas solicitudes:”

      /etc/nginx/sites-available/myproject

      server {
          listen 80;
          server_name server_domain_or_IP;
      
          location = /favicon.ico { access_log off; log_not_found off; }
          location /static/ {
              root /home/sammy/myprojectdir;
          }
      }
      

      Por último, crearemos un bloque location / {} para que coincida con todas las demás solicitudes. Dentro de esta ubicación, agregaremos el archivo proxy_params estándar incluido con la instalación de Nginx y luego transferiremos el tráfico directamente al socket de Gunicorn:

      /etc/nginx/sites-available/myproject

      server {
          listen 80;
          server_name server_domain_or_IP;
      
          location = /favicon.ico { access_log off; log_not_found off; }
          location /static/ {
              root /home/sammy/myprojectdir;
          }
      
          location / {
              include proxy_params;
              proxy_pass http://unix:/run/gunicorn.sock;
          }
      }
      

      Guarde y cierre el archivo cuando termine. Ahora, podemos habilitar el archivo vinculándolo al directorio sites-enabled:

      • sudo ln -s /etc/nginx/sites-available/myproject /etc/nginx/sites-enabled

      Pruebe su configuración de Nginx para descartar errores de sintaxis escribiendo lo siguiente:

      Si no se notifican errores, reinicie Nginx escribiendo lo siguiente:

      • sudo systemctl restart nginx

      Por último, debemos abrir nuestro firewall al tráfico normal en el puerto 80. Como ya no necesitamos acceso al servidor de desarrollo, podemos eliminar la regla para abrir también el puerto 8000:

      • sudo ufw delete allow 8000
      • sudo ufw allow 'Nginx Full'

      Ahora debería poder acceder al dominio o a la dirección IP de su servidor para ver su aplicación.

      Nota: Después de configurar Nginx, el siguiente paso debería ser proteger el tráfico al servidor usando SSL/TLS. Esto es importante porque, si no se aplica, toda la información, incluidas las contraseñas, se envía a través de la red en texto simple.

      Si tiene un nombre de dominio, la alternativa más sencilla para obtener un certificado SSL para proteger su tráfico es usar Let’s Encrypt. Siga esta guía para configurar Let’s Encrypt con Nginx en Ubuntu 18.04. Siga el procedimiento usando el bloque de servidor de Nginx que creamos en esta guía.

      Si no tiene un nombre de dominio, aún puede proteger su sitio para pruebas y aprendizaje con un certificado SSL autofirmado. Nuevamente, siga el proceso usando el bloque de servidor Nginx que creamos en este tutorial.

      Resolver problemas en Nginx y Gunicorn

      Si con este último paso no se muestra su aplicación, deberá resolver problemas en su instalación.

      Nginx muestra la página predeterminada en lugar de la aplicación de Django

      Si Nginx muestra la página predeterminada en lugar de actualizar su aplicación, normalmente significa que deberá ajustar el server_name dentro del archivo /etc/nginx/sites-available/myproject para apuntar a la dirección IP o al nombre de dominio de su servidor.

      Nginx usa el server_name para determinar el bloque de servidor que usará para responder a solicitudes. Si ve la página predeterminada de Nginx, significa que Nginx no pudo hacer coincidir la solicitud con un bloque de servidor de forma explícita, por lo cual recurre al bloque por defecto definido en /etc/nginx/sites-available/default.

      El server_name del bloque de servidor de su proyecto debe ser más específico que el del bloque de servidor predeterminado que se seleccionará.

      Nginx muestra un error de puerta de enlace 502 en lugar de la aplicación de Django

      Un error 502 indica que Nginx no puede autorizar con éxito la solicitud. Con el error 502 se transmite una amplia variedad de problemas de configuración, por lo que se necesita más información para resolver los problemas de forma adecuada.

      Los registros de errores de Nginx son el recurso principal para buscar más información. Generalmente, esto le indicará las condiciones que ocasionaron problemas durante el evento de autorización. Siga los registros de errores de Nginx escribiendo lo siguiente:

      • sudo tail -F /var/log/nginx/error.log

      Ahora, realice otra solicitud en su navegador para generar un nuevo error (intente actualizar la página). Debería ver un nuevo mensaje de error escrito en el registro. Si ve el mensaje, le servirá para reducir el problema.

      Es posible que vea algunos de los mensajes que se muestran a continuación:

      connect() to unix:/run/gunicorn.sock failed (2: No such file or directory)

      Esto indica que Nginx no pudo encontrar el archivo gunicorn.sock en la ubicación en cuestión. Debería comparar la ubicación de proxy_pass definida en el archivo /etc/nginx/sites-available/myproject con la ubicación actual del archivo gunicorn.sock generado por la unidad de systemd gunicorn.sock.

      Si no puede encontrar un archivo gunicorn.sock en el directorio /run, por lo general significa que el archivo de socket de systemd no pudo crearlo. Regrese a la sección de verificación del archivo de socket de Gunicorn para seguir los pasos de resolución de problemas de Gunicorn.

      connect() to unix:/run/gunicorn.sock failed (13: Permission denied)

      Esto indica que Nginx no pudo conectarse al socket de Gunicorn debido a problemas de permisos. Esto puede ocurrir cuando se sigue el procedimiento con un usuario root en lugar de un usuario sudo. Aunque systemd puede crear el archivo de socket de Gunicorn, Nginx no puede acceder a él.

      Esto puede ocurrir si existen permisos limitados en cualquier punto entre el directorio root (/) y el archivo gunicorn.sock. Podemos ver los permisos y valores de propiedad del archivo de socket y cada uno de sus directorios pasando la ruta absoluta a nuestro archivo de socket al comando namei:

      • namei -l /run/gunicorn.sock

      Output

      f: /run/gunicorn.sock drwxr-xr-x root root / drwxr-xr-x root root run srw-rw-rw- root root gunicorn.sock

      En el resultado se muestran los permisos de cada uno de los componentes del directorio. Al mirar los permisos (primera columna), el propietario (segunda columna) y el propietario del grupo (tercera columna), podemos averiguar el tipo de acceso permitido para el archivo de socket.

      En el ejemplo anterior, el archivo de sockets y cada directorio que conduce a este tienen permisos mundiales de lectura y ejecución (la columna de permisos para los directorios termina en r-x en lugar de ---). El proceso de Nginx debería poder acceder al socket de forma correcta.

      Si algunos directorios que conducen al socket no tienen permiso mundial de lectura y ejecución, Nginx no podrá acceder al socket sin otorgar permisos mundiales de lectura y ejecución ni asegurarse de que se otorgue propiedad del grupo a un grupo del que forme parte Nginx.

      Django muestra el mensaje “could not connect to server: Connection refused”

      Se puede ver el el siguiente mensaje de Django al intentar acceder a partes de la aplicación en el navegador web:

      OperationalError at /admin/login/
      could not connect to server: Connection refused
          Is the server running on host "localhost" (127.0.0.1) and accepting
          TCP/IP connections on port 5432?
      

      Esto indica que Django no puede conectarse a la base de datos de Postgres. Asegúrese de que la instancia de Postgres esté en ejecución escribiendo lo siguiente:

      • sudo systemctl status postgresql

      Si esto no sucede, puede iniciarla y activarla para que se cargue automáticamente en el inicio (si aún no está cargada la configuración para ello) escribiendo lo siguiente:

      • sudo systemctl start postgresql
      • sudo systemctl enable postgresql

      Si todavía experimenta problemas, asegúrese de que los ajustes de la base de datos definidos en el archivo ~/myprojectdir/myproject/settings.py sean correctos.

      Solución de problemas adicionales

      Para resolver problemas adicionales, los registros pueden servir para reducir las causas raíces. Verifique cada uno de ellos por separado y busque mensajes que indiquen las áreas problemáticas.

      Los siguientes registros pueden ser útiles:

      • Verifique los registros de proceso de Nginx escribiendo lo siguiente: sudo journalctl -u nginx.
      • Verifique los registros de acceso de Nginx escribiendo lo siguiente: sudo less /var/log/nginx/access.log
      • Verifique los registros de errores de Nginx escribiendo lo siguiente: sudo less /var/log/nginx/error.log.
      • Verifique los registros de la aplicación de Gunicorn escribiendo lo siguiente: sudo journalctl -u gunicorn.
      • Verifique los registros de sockets de Gunicorn escribiendo lo siguiente: sudo journalctl -u gunicorn.socket.

      Cuando actualice su configuración o aplicación, es probable que necesite reiniciar los procesos para que asimilen sus cambios.

      Si actualiza su aplicación de Django, puede reiniciar el proceso de Gunicorn para que incorpore los cambios escribiendo lo siguiente:

      • sudo systemctl restart gunicorn

      Si cambia los archivos de socket y servicio de Gunicorn, vuelva a cargar el demonio y reinicie el proceso escribiendo lo siguiente:

      • sudo systemctl daemon-reload
      • sudo systemctl restart gunicorn.socket gunicorn.service

      Si cambia la configuración de bloque del servidor de Nginx, pruébela y luego verifique Nginx escribiendo lo siguiente:

      • sudo nginx -t && sudo systemctl restart nginx

      Estos comandos son útiles para incorporar cambios cuando ajusta su configuración.

      Conclusión

      En esta guía, creamos un proyecto de Django en su propio entorno virtual. Configuramos Gunicorn para que traduzca las solicitudes de los clientes a fin de que Django pueda manejarlas. Posteriormente, configuramos Nginx para que actúe como proxy inverso a fin de manejar las conexiones de los clientes y presentar el proyecto correcto según la solicitud del cliente.

      Django simplifica la creación de proyectos y aplicaciones proporcionando muchas de las piezas comunes, lo que le permite centrarse en los elementos únicos. Al aprovechar la cadena general de herramientas descrita en este artículo, puede ofrecer fácilmente las aplicaciones que cree desde un servidor único.



      Source link

      Cómo crear una aplicación web moderna para gestionar la información de clientes con Django y React on Ubuntu 18.04


      El autor seleccionó Open Sourcing Mental Illness Ltd para recibir una donación como parte del programa Write for Donations.

      Introducción

      Las personas utilizan diferentes tipos de dispositivos para conectarse a internet y navegar por la Web. Debido a esto, las aplicaciones deben ser accesibles desde varios lugares. Para los sitios web tradicionales, tener una IU receptiva suele ser suficiente, pero las aplicaciones más complejas suelen requerir el uso de otras técnicas y arquitecturas. Entre ellas se contempla tener aplicaciones back-end y front-end REST independientes que puedan implementarse como aplicaciones web para el cliente, aplicaciones web progresivas (PWA) o aplicaciones móviles nativas.

      Algunas herramientas que puede utilizar al crear aplicaciones más complejas incluyen:

      • React, un marco de trabajo de JavaScript que permite a los desarrolladores crear frontends web y nativos para sus backend de API REST.
      • Django, una estructura web de Python gratuita y de código abierto que sigue el patrón de arquitectura del software de modelo vista controlador (MVC).
      • Django REST framework, un conjunto de herramientas potentes y flexibles para el desarrollo de REST APIs en Django.

      En este tutorial, usted creará una aplicación web moderna con un backend REST API independiente y un frontend utilizando React, Django y Django REST Framework. Al utilizar React con Django, podrá beneficiarse de los últimos avances en el desarrollo de JavaScript y front-end. En lugar de crear una aplicación de Django que utilice un motor de plantillas incorporado, usted utilizará React como biblioteca de IU, aprovechando su enfoque virtual de Modelo de objetos de documentos (DOM), enfoque declarativo y componentes que rápidamente reproduzcan cambios en los datos.

      La aplicación web que usted creará almacena registros sobre clientes en una base de datos, y puede utilizarlo como punto de partida para una aplicación CRM. Cuando haya terminado, podrá crear, leer, actualizar y borrar registros utilizando una interfaz React de estilo Bootstrap 4.

      Requisitos previos

      Para completar este tutorial, necesitará lo siguiente:

      Paso 1: Creación de un entorno virtual de Python e instalación de dependencias

      En este paso, crearemos un entorno virtual e instalaremos las dependencias necesarias para nuestra aplicación, entre ellas, Django, Django REST framework y django-cors-headers.

      Nuestra aplicación utilizará dos servidores de desarrollo distintos para Django y React. Se ejecutarán en diferentes puertos y funcionarán como dos dominios separados. Debido a esto, debemos permitir el intercambio de recursos de origen cruzado (CORS) para enviar solicitudes HTTP desde React a Django sin que el navegador pueda bloquearlos.

      Navegue a su directorio principal y cree un entorno virtual utilizando el módulo venv Python 3:

      • cd ~
      • python3 -m venv ./env

      Active el entorno virtual creado utilizando “source:

      A continuación, instale las dependencias del proyecto con pip. Entre ellas se incluyen:

      • Django: el marco de trabajo web para el proyecto.
      • Django REST framework: Una aplicación externa que desarrolla REST APIs con Django.
      • django-cors-headers: un paquete que habilita CORS.

      Instalar la estructura de Django:

      • pip install django djangorestframework django-cors-headers

      Con las dependencias del proyecto instaladas, puede crear el proyecto Django y el frontend de React.

      Paso 2: Creación del proyecto Django

      En este paso, generaremos el proyecto Django utilizando las siguientes comandos y utilidades:

      • **django-admin startproject project-name**:django-admin es una utilidad de línea de comandos que se utiliza para realizar tareas con Django. El comando startproject crea un nuevo proyecto Django.

      • **python manage.py startapp myapp**: manage.py es un script de utilidad que se añade automáticamente a cada proyecto de Django, y que ejecuta varias tareas administrativas, como crear nuevas aplicaciones, migrar la base de datos y servir de forma local el proyecto de Django. Su comando startapp crea una aplicación de Django dentro del proyecto Django. En Django, el término aplicación describe un paquete de Python que proporciona algunas características en un proyecto.

      Para comenzar, cree el proyecto Django con django-admin startproject. Hemos de nombrar a nuestro proyecto djangoreactproject

      • django-admin startproject djangoreactproject

      Antes de seguir, observemos la estructura del directorio de nuestro proyecto Django utilizando el comando tree.

      Nota: tree es un comando útil para visualizar estructuras de archivos y directorio desde la línea de comandos. Puede instalarlo con el comando que se indica a continuación:

      • sudo apt-get install tree

      Para utilizarlo, use el comando cd en el directorio que desee y escriba tree o proporcione la ruta al punto de partida con tree /home/sammy/sammys-project.

      Navegue a la carpeta djangoreactproject dentro del root de su proyecto y ejecute el comando tree:

      • cd ~/djangoreactproject
      • tree

      Verá lo siguiente:

      Output

      ├── djangoreactproject │ ├── __init__.py │ ├── settings.py │ ├── urls.py │ └── wsgi.py └── manage.py

      La carpeta ~/djangoreactproject es la root del proyecto. Dentro de esta carpeta, hay varios archivos que serán importantes para su labor:

      • manage.py: el script de utilidad que realiza diversas tareas administrativas.
      • settings.py: el archivo de configuración principal para el proyecto de Django, donde puede modificar la configuración del proyecto. Estos ajustes incluyen variables como INSTALLED_APPS, una lista de strings que designan las aplicaciones habilitadas para su proyecto. La documentación de Django contiene más información sobre los ajustes disponibles.
      • urls.py: este archivo contiene una lista de patrones de URL y vistas relacionadas. Cada patrón traza una conexión entre una URL y la función que se debe solicitar para esa URL. Para más información sobre URL y vistas, consulte nuestro tutorial sobre Cómo crear vistas de Django.

      Nuestro primer paso en el trabajo con el proyecto será configurar los paquetes que instalamos en el paso anterior, incluidos Django REST framework y el paquete Django CORS, al añadirlos a settings.py. Abra el archivo con nano o su editor favorito:

      • nano ~/djangoreactproject/djangoreactproject/settings.py

      Navegue al ajuste INSTALLED_APPS y añada las aplicaciones rest_framework y corsheaders en la parte inferior de la lista:

      ~/djangoreactproject/djangoreactproject/settings.py

      ...
      INSTALLED_APPS = [
          'django.contrib.admin',
          'django.contrib.auth',
          'django.contrib.contenttypes',
          'django.contrib.sessions',
          'django.contrib.messages',
          'django.contrib.staticfiles',
          'rest_framework',
          'corsheaders'
      ]
      

      A continuación, añada el middleware corsheaders.middleware.CorsMiddleware desde el paquete CORS instalado previamente al ajuste MIDDLEWARE. Este ajuste es una lista de middlewares, una clase de Python que contiene código que se procesa cada vez que su aplicación web gestiona una solicitud o respuesta:

      ~/djangoreactproject/djangoreactproject/settings.py

      ...
      
      MIDDLEWARE = [
      ...
      'django.contrib.messages.middleware.MessageMiddleware',
      'django.middleware.clickjacking.XFrameOptionsMiddleware',
      'corsheaders.middleware.CorsMiddleware'
      ]
      

      A continuación, puede habilitar CORS. El ajuste CORS_ORIGIN_ALLOW_ALL especifica si desea habilitar CORS para todos los dominios o no, y CORS_ORIGIN_WHITELIST es una tupla de Python que contiene URL permitidas. En nuestro caso, dado que el servidor de desarrollo de React se ejecutará en http://localhost:3000, añadiremos nuevos ajustes CORS_ORIGIN_ALLOW_ALL = False y CORS_ORIGIN_WHITELIST('localhost:3000',) a nuestro archivo settings.py. Añade estos ajustes en cualquier parte del archivo:

      ~/djangoreactproject/djangoreactproject/settings.py

      
      ...
      CORS_ORIGIN_ALLOW_ALL = False
      
      CORS_ORIGIN_WHITELIST = (
             'localhost:3000',
      )
      ...
      

      Puede encontrar más opciones de configuración en la documentación de django-cors-headers.

      Guarde el archivo y salga del editor cuando haya terminado.

      Aún en el directorio ~/djangoreactproject, cree una nueva aplicación de Django llamada customers:

      • python manage.py startapp customers

      Contendrá los modelos y las vistas para gestionar clientes. Los modelos definen los campos y los comportamientos de nuestros datos de aplicaciones, mientras que las vistas permiten a nuestras aplicaciones gestionar adecuadamente las solicitudes web y devolver las respuestas requeridas.

      A continuación, añada esta aplicación a la lista de aplicaciones instaladas en el archivo settings.py de su proyecto para que Django la reconozca como parte del proyecto. Abra settings.py de nuevo:

      • nano ~/djangoreactproject/djangoreactproject/settings.py

      Añada la aplicación customers:

      ~/djangoreactproject/djangoreactproject/settings.py

      ...
      INSTALLED_APPS = [
          ...
          'rest_framework',
          'corsheaders',
          'customers'
      ]
      ...
      

      A continuación, *migre *la base de datos e inicie el servidor de desarrollo local. Las migraciones son la manera en que Django propaga los cambios que usted realiza a sus modelos en su esquema de base de datos. Estos cambios pueden ser, por ejemplo, añadir un campo o eliminar un modelo. Para obtener más información sobre modelos y migraciones, consulte Cómo crear modelos de Django.

      Migre la base de datos:

      Inicie el servidor de desarrollo local:

      • python manage.py runserver

      El resultado debe ser similar a lo siguiente:

      Output

      Performing system checks... System check identified no issues (0 silenced). October 22, 2018 - 15:14:50 Django version 2.1.2, using settings 'djangoreactproject.settings' Starting development server at http://127.0.0.1:8000/ Quit the server with CONTROL-C.

      Su aplicación web se ejecuta desde http://127.0.0.1:8000. Si se dirige a esta dirección en su navegador web, debería ver la siguiente página:

      Página de demostración de Django

      En este momento, deje la aplicación en ejecución y abra una nueva terminal para seguir desarrollando el proyecto.

      Paso 3: creación del frontend de React

      En esta sección, vamos a crear la aplicación frontend de nuestro proyecto utilizando React.

      React tiene una herramienta oficial que le permite generar proyectos de React de forma rápida sin tener que configurar Webpack directamente. Webpack es un empaquetador de módulos que se utiliza para agrupar recursos web, como código de JavaScript, CSS e imágenes. Normalmente, para poder utilizar Webpack, debe establecer varias opciones de configuración, pero, gracias a la herramienta create-react-app, no tiene que lidiar con Webpack directamente hasta que decida que necesita más control. Para ejecutar create-react-app puede utilizar npx, una herramienta que ejecuta binarios de paquetes npm.

      En su segunda terminal, asegúrese de que estar en el directorio de su proyecto:

      Cree un proyecto de React llamado frontend utilizando create-react-app y npx

      • npx create-react-app frontend

      A continuación, navegue al interior de su aplicación de React e inicie el servidor de desarrollo:

      • cd ~/djangoreactproject/frontend
      • npm start

      Su aplicación se ejecutará desde http://localhost:3000/:

      Página de demostración de React

      Deje el servidor de desarrollo de React en ejecución y abra otra ventana de terminal para proceder.

      Para ver la estructura del directorio de todo el proyecto en este punto, navegue a la carpeta root y ejecute el comando tree de nuevo:

      • cd ~/djangoreactproject
      • tree

      Verá una estructura como esta:

      Output

      ├── customers │ ├── admin.py │ ├── apps.py │ ├── __init__.py │ ├── migrations │ │ └── __init__.py │ ├── models.py │ ├── tests.py │ └── views.py ├── djangoreactproject │ ├── __init__.py │ ├── __pycache__ │ ├── settings.py │ ├── urls.py │ └── wsgi.py ├── frontend │ ├── package.json │ ├── public │ │ ├── favicon.ico │ │ ├── index.html │ │ └── manifest.json │ ├── README.md │ ├── src │ │ ├── App.css │ │ ├── App.js │ │ ├── App.test.js │ │ ├── index.css │ │ ├── index.js │ │ ├── logo.svg │ │ └── registerServiceWorker.js │ └── yarn.lock └── manage.py

      Nuestra aplicación utilizará Bootstrap 4 para dar forma a la interfaz de React, por lo que lo incluiremos en el archivo frontend/src/App.css que gestiona nuestros ajustes de CSS. Abra el archivo:

      • nano ~/djangoreactproject/frontend/src/App.css

      Añada la importación que se indica a continuación al comienzo del archivo. Puede eliminar el contenido existente del archivo, pero no es necesario hacerlo:

      ~/djangoreactproject/frontend/src/App.css

      @import  'https://maxcdn.bootstrapcdn.com/bootstrap/4.0.0/css/bootstrap.min.css';
      

      Aquí, @import es una instrucción de CSS que se utiliza para importar reglas de estilo de otras hojas de estilo.

      Ahora que hemos creado las aplicaciones back-end y front-end, vamos a crear el modelo de cliente y algunos datos de prueba.

      Paso 4: creación del modelo de cliente y datos iniciales

      Tras crear la aplicación de Django y el frontend de React, nuestro próximo paso será crear el modelo de cliente, que representa la tabla de base de datos que almacenará información sobre los clientes. No necesita nada de SQL, dado que el mapeo objeto-relacional (ORM) de Django se encargará de las operaciones de la base de datos al asignar las clases y variables de Python a tablas y columnas de SQL. De esta manera, el ORM de Django extrae las interacciones de SQL con la base de datos a través de una interfaz de Python.

      Active su entorno virtual de nuevo:

      • cd ~
      • source env/bin/activate

      Diríjase al directorio customers y abra models.py, un archivo de Python que contiene los modelos de su aplicación:

      • cd ~/djangoreactproject/customers/
      • nano models.py

      El archivo incluirá el siguiente contenido:

      ~/djangoreactproject/customers/models.py

      from django.db import models
      # Create your models here.
      

      La API del modelo de cliente ya está importada en el archivo gracias a la instrucción import from django.db import models. Ahora, añadirá la clase Customer, que extiende models.Model. Cada modelo de Django es una clase de Python que extiende django.db.models.Model.

      El modelo Customer tendrá estos campos de base de datos:

      • first_name: el nombre del cliente.
      • last_name: el apellido del cliente.
      • email: la dirección de correo electrónico del cliente.
      • phone: el número de teléfono del cliente.
      • address: la dirección del cliente.
      • description: la descripción del cliente.
      • createdAt: la fecha en que se añade el cliente.

      También añadiremos la función __str__(), que define la manera en que se mostrará el modelo. En nuestro caso, será con el nombre del cliente. Para obtener más información sobre la creación de clases y la definición de objetos, consulte Cómo crear clases y definir objetos en Python 3.

      Añada el código siguiente al archivo:

      ~/djangoreactproject/customers/models.py

      from django.db import models
      
      class Customer(models.Model):
          first_name = models.CharField("First name", max_length=255)
          last_name = models.CharField("Last name", max_length=255)
          email = models.EmailField()
          phone = models.CharField(max_length=20)
          address =  models.TextField(blank=True, null=True)
          description = models.TextField(blank=True, null=True)
          createdAt = models.DateTimeField("Created At", auto_now_add=True)
      
          def __str__(self):
              return self.first_name
      

      A continuación, migre la base de datos para crear las tablas de la base de datos. El comando makemigrations crea los archivos de migración en los que se añadirán los cambios al modelo, y migrate aplica los cambios en los archivos de migraciones a la base de datos.

      Vuelva a navegar a la carpeta root del proyecto:

      Ejecute lo siguiente para crear los archivos de migración:

      • python manage.py makemigrations

      Verá algo similar a esto:

      Output

      customers/migrations/0001_initial.py - Create model Customer

      Aplique estos cambios en la base de datos:

      Verá un resultado que indica que la migración se realizó correctamente:

      Output

      Operations to perform: Apply all migrations: admin, auth, contenttypes, customers, sessions Running migrations: Applying customers.0001_initial... OK

      A continuación, utilizará un archivo de migración de datos para crear datos iniciales de clientes. Un archivo de migración de datos es una migración que añade o altera datos en la base de datos. Cree un archivo de migración de datos vacío para la aplicación customers:

      • python manage.py makemigrations --empty --name customers customers

      Visualizará la siguiente confirmación con el nombre de su archivo de migración:

      Output

      Migrations for 'customers': customers/migrations/0002_customers.py

      Tenga en cuenta que el nombre de su archivo de migración es 0002_customers.py.

      A continuación, navegue al interior de la carpeta de migraciones de la aplicación customers:

      • cd ~/djangoreactproject/customers/migrations

      Abra el archivo de migración creado:

      Este es el contenido inicial del archivo:

      ~/djangoreactproject/customers/migrations/0002_customers.py

      from django.db import migrations
      
      class Migration(migrations.Migration):
          dependencies = [
              ('customers', '0001_initial'),
          ]
          operations = [
          ]        
      

      La instrucción import importa la API de migraciones, una API de Django para crear migraciones, desde django.db, un paquete incorporado que contiene clases para trabajar con bases de datos.

      La clase Migration es una clase de Python que describe las operaciones que se ejecutan al migrar bases de datos. Esta clase extiende migrations.Migration y tiene dos listas:

      • dependencies: contiene las migraciones dependientes.
      • operations: contiene las operaciones que se ejecutarán al aplicar la migración.

      A continuación, añada un método para crear datos de clientes de prueba. Añada el método que se indica a continuación antes de la definición de la clase Migration:

      ~/djangoreactproject/customers/migrations/0002_customers.py

      ...
      def create_data(apps, schema_editor):
          Customer = apps.get_model('customers', 'Customer')
          Customer(first_name="Customer 001", last_name="Customer 001", email="customer001@email.com", phone="00000000", address="Customer 000 Address", description= "Customer 001 description").save()
      
      ...
      

      En este método, estamos tomando la clase Customer de nuestra aplicación customers y creando un cliente de prueba para insertar en la base de datos.

      Para obtener la clase Customer, que permitirá la creación de nuevos clientes, usamos el método get_model() del objeto apps. El objeto apps representa el registro de aplicaciones instaladas y sus modelos de base de datos.

      El objeto apps se pasará del método RunPython() cuando lo usemos para ejecutar create_data(). Añada el método migrations.RunPython() a la lista operations vacía:

      ~/djangoreactproject/customers/migrations/0002_customers.py

      
      ...
          operations = [
              migrations.RunPython(create_data),
          ]  
      

      RunPython() es parte de la API de Migrations que le permite ejecutar código de Python personalizado en una migración. Nuestra lista operations especifica que este método se ejecutará al aplicar la migración.

      Este es el archivo completo:

      ~/djangoreactproject/customers/migrations/0002_customers.py

      from django.db import migrations
      
      def create_data(apps, schema_editor):
          Customer = apps.get_model('customers', 'Customer')
          Customer(first_name="Customer 001", last_name="Customer 001", email="customer001@email.com", phone="00000000", address="Customer 000 Address", description= "Customer 001 description").save()
      
      class Migration(migrations.Migration):
          dependencies = [
              ('customers', '0001_initial'),
          ]
          operations = [
              migrations.RunPython(create_data),
          ]        
      

      Para obtener más información sobre migraciones de datos, consulte la documentación sobre migraciones de datos en Django

      Para migrar su base de datos, primero, vuelva a navegar a la carpeta root de su proyecto:

      Migre su base de datos para crear los datos de prueba:

      Visualizará un resultado que confirma la migración:

      Output

      Operations to perform: Apply all migrations: admin, auth, contenttypes, customers, sessions Running migrations: Applying customers.0002_customers... OK

      Para obtener más detalles sobre este proceso, consulte Cómo crear modelos de Django.

      Con el modelo Customer y los datos de prueba creados, podemos pasar a la creación de la API REST.

      Paso 5: creación de la API REST

      En este paso, vamos a crear la API REST utilizando Django REST Framework. Crearemos varias vistas de API diferentes. Una vista de API es una función que gestiona una solicitud o llamada de API, mientras que un punto de final de API es una URL única que representa un punto de contacto con el sistema REST. Por ejemplo, cuando el usuario envía una solicitud de GET a un punto final de API, Django llama a la función o vista de API correspondiente para gestionar la solicitud y devolver los resultados posibles.

      También utilizaremos serializadores. Un serializador de Django REST Framework permite que instancias de modelos complejas y QuerySets se conviertan en formato JSON para el consumo de API. La clase de serialización también puede funcionar en dirección inversa, proporcionando mecanismos para el análisis y la deserialización de datos en QuerySets y modelos de Django.

      Nuestros puntos finales de API incluirán lo siguiente:

      • api/customers: este punto final se utiliza para crear clientes y devuelve conjuntos paginados de clientes.
      • api/clusters/<pk>: este punto final se utiliza para obtener, actualizar y eliminar clientes individuales por clave primaria o id.

      También crearemos URL en el archivo urls.py del proyecto para los puntos finales correspondientes (es decir, api/clusters y api/clusters/<pk>).

      Comencemos por crear la clase de serialización para nuestro modelo Customer.

      Incorporación de la clase de serialización

      Es necesario crear una clase de serialización para nuestro modelo Customer para transformar las instancias de cliente y QuerySets hacia y desde JSON. Para crear la clase de serialización, primero, cree un archivo serializer.py dentro de la aplicación customers:

      • cd ~/djangoreactproject/customers/
      • nano serializers.py

      Añada el código siguiente para importar el modelo Customer y la API de serializadores:

      ~/djangoreactproject/customers/serializers.py

      from rest_framework import serializers
      from .models import Customer
      

      A continuación, cree una clase de serialización que extienda serializers.ModelSerializer y especifique los campos que han de serializarse:

      ~/djangoreactproject/customers/serializers.py

      
      ...
      class CustomerSerializer(serializers.ModelSerializer):
      
          class Meta:
              model = Customer 
              fields = ('pk','first_name', 'last_name', 'email', 'phone','address','description')
      

      La clase Meta especifica qué campos y modelos se serializarán: pk, first_name, last_name, email, phone, address, description.

      Este es el contenido completo del archivo:

      ~/djangoreactproject/customers/serializers.py

      from rest_framework import serializers
      from .models import Customer
      
      class CustomerSerializer(serializers.ModelSerializer):
      
          class Meta:
              model = Customer 
              fields = ('pk','first_name', 'last_name', 'email', 'phone','address','description')
      

      Ahora que hemos creado nuestra clase de serialización, podemos añadir las vistas de API.

      Incorporación de vistas de API

      En esta sección, crearemos las vistas de API para nuestra aplicación, a las que llamará Django cuando el usuario visite el punto final correspondiente a la función de vista.

      Abra ~/djangoreactproject/customers/views.py:

      • nano ~/djangoreactproject/customers/views.py

      Elimine lo que haya allí y añada las siguientes importaciones:

      ~/djangoreactproject/customers/views.py

      from rest_framework.response import Response
      from rest_framework.decorators import api_view
      from rest_framework import status
      
      from django.core.paginator import Paginator, EmptyPage, PageNotAnInteger
      from .models import Customer 
      from .serializers import *
      

      Estamos importando el serializador que creamos, junto con el modelo Customer y las API de Django y Django REST Framework.

      A continuación, añada la vista para el procesamiento de POST y las solicitudes GET HTTP:

      ~/djangoreactproject/customers/views.py

      ...
      
      @api_view(['GET', 'POST'])
      def customers_list(request):
          """
       List  customers, or create a new customer.
       """
          if request.method == 'GET':
              data = []
              nextPage = 1
              previousPage = 1
              customers = Customer.objects.all()
              page = request.GET.get('page', 1)
              paginator = Paginator(customers, 10)
              try:
                  data = paginator.page(page)
              except PageNotAnInteger:
                  data = paginator.page(1)
              except EmptyPage:
                  data = paginator.page(paginator.num_pages)
      
              serializer = CustomerSerializer(data,context={'request': request} ,many=True)
              if data.has_next():
                  nextPage = data.next_page_number()
              if data.has_previous():
                  previousPage = data.previous_page_number()
      
              return Response({'data': serializer.data , 'count': paginator.count, 'numpages' : paginator.num_pages, 'nextlink': '/api/customers/?page=' + str(nextPage), 'prevlink': '/api/customers/?page=' + str(previousPage)})
      
          elif request.method == 'POST':
              serializer = CustomerSerializer(data=request.data)
              if serializer.is_valid():
                  serializer.save()
                  return Response(serializer.data, status=status.HTTP_201_CREATED)
              return Response(serializer.errors, status=status.HTTP_400_BAD_REQUEST)
      

      Primero, usamos el decorador @api_view(['GET', 'POST']) para crear una vista de API que pueda aceptar solicitudes GET y POST. Un decorador es una función que toma otra función y la extiende de forma dinámica.

      En el cuerpo del método, usamos la variable request.method para verificar el método HTTP actual y ejecutar la lógica correspondiente dependiendo del tipo de solicitud:

      • Si se trata de una solicitud GET, el método pagina los datos utilizando Django Paginator y devuelve a la primera página de datos después de la serialización, el conteo de clientes disponibles, el número de páginas disponibles y los enlaces a las páginas anteriores y siguientes. Paginator es una clase integrada de Django que pagina una lista de datos en páginas y proporciona métodos para acceder a los elementos de cada una de ellas.
      • Si se trata de una solicitud POST, el método serializa los datos de clientes recibidos y, luego, llama al método save() del objeto serializador. A continuación, devuelve un objeto de Response, una instancia de HttpResponse, con el código de estado 201. Cada vista que crea se encarga de regresar un objeto HttpResponse. El método save() guarda los datos serializados en la base de datos.

      Para obtener más información sobre HttpResponse y las vistas, consulte esta discusión con respecto a la creación de funciones de vista.

      Ahora, añada la vista de API que se encargará del procesamiento de las solicitudes GET, PUT y DELETE para obtener, actualizar y eliminar clientes por pk (clave primaria):

      ~/djangoreactproject/customers/views.py

      
      ...
      @api_view(['GET', 'PUT', 'DELETE'])
      def customers_detail(request, pk):
       """
       Retrieve, update or delete a customer by id/pk.
       """
          try:
              customer = Customer.objects.get(pk=pk)
          except Customer.DoesNotExist:
              return Response(status=status.HTTP_404_NOT_FOUND)
      
          if request.method == 'GET':
              serializer = CustomerSerializer(customer,context={'request': request})
              return Response(serializer.data)
      
          elif request.method == 'PUT':
              serializer = CustomerSerializer(customer, data=request.data,context={'request': request})
              if serializer.is_valid():
                  serializer.save()
                  return Response(serializer.data)
              return Response(serializer.errors, status=status.HTTP_400_BAD_REQUEST)
      
          elif request.method == 'DELETE':
              customer.delete()
              return Response(status=status.HTTP_204_NO_CONTENT)
      

      El método está representado con @api_view(['GET', 'PUT', 'DELETE']) para indicar que se trata de una vista de API que puede aceptar las solicitudes GET, PUT y DELETE.

      La marca de revisión en el campo request.method verifica el método de solicitud y, dependiendo de su valor, llama a la lógica correcta:

      • Si se trata de una solicitud GET, se serializan los datos de clientes y se envían utilizando un objeto Response.
      • Si se trata de una solicitud PUT, el método crea un serializador para nuevos datos de cliente y, luego, llama al método save() del objeto serializador creado. Por último, envía un objeto Response con el cliente actualizado.
      • Si se trata de una solicitud DELETE, el método llama al método delete() del objeto de cliente para eliminarlo y, a continuación, devuelve un objeto Response sin datos.

      El archivo completo se ve de este modo:

      ~/djangoreactproject/customers/views.py

      from rest_framework.response import Response
      from rest_framework.decorators import api_view
      from rest_framework import status
      
      from django.core.paginator import Paginator, EmptyPage, PageNotAnInteger
      from .models import Customer 
      from .serializers import *
      
      
      @api_view(['GET', 'POST'])
      def customers_list(request):
          """
       List  customers, or create a new customer.
       """
          if request.method == 'GET':
              data = []
              nextPage = 1
              previousPage = 1
              customers = Customer.objects.all()
              page = request.GET.get('page', 1)
              paginator = Paginator(customers, 5)
              try:
                  data = paginator.page(page)
              except PageNotAnInteger:
                  data = paginator.page(1)
              except EmptyPage:
                  data = paginator.page(paginator.num_pages)
      
              serializer = CustomerSerializer(data,context={'request': request} ,many=True)
              if data.has_next():
                  nextPage = data.next_page_number()
              if data.has_previous():
                  previousPage = data.previous_page_number()
      
              return Response({'data': serializer.data , 'count': paginator.count, 'numpages' : paginator.num_pages, 'nextlink': '/api/customers/?page=' + str(nextPage), 'prevlink': '/api/customers/?page=' + str(previousPage)})
      
          elif request.method == 'POST':
              serializer = CustomerSerializer(data=request.data)
              if serializer.is_valid():
                  serializer.save()
                  return Response(serializer.data, status=status.HTTP_201_CREATED)
              return Response(serializer.errors, status=status.HTTP_400_BAD_REQUEST)
      
      @api_view(['GET', 'PUT', 'DELETE'])
      def customers_detail(request, pk):
          """
       Retrieve, update or delete a customer by id/pk.
       """
          try:
              customer = Customer.objects.get(pk=pk)
          except Customer.DoesNotExist:
              return Response(status=status.HTTP_404_NOT_FOUND)
      
          if request.method == 'GET':
              serializer = CustomerSerializer(customer,context={'request': request})
              return Response(serializer.data)
      
          elif request.method == 'PUT':
              serializer = CustomerSerializer(customer, data=request.data,context={'request': request})
              if serializer.is_valid():
                  serializer.save()
                  return Response(serializer.data)
              return Response(serializer.errors, status=status.HTTP_400_BAD_REQUEST)
      
          elif request.method == 'DELETE':
              customer.delete()
              return Response(status=status.HTTP_204_NO_CONTENT)
      

      Ahora, podemos pasar a crear nuestros puntos finales.

      Incorporación de puntos finales de API

      Ahora, crearemos los puntos finales de API: api/customers/ para consultar y crear clientes, y api/customers/ <pk> para obtener, actualizar o eliminar clientes individuales por su pk.

      Abra ~/djangoreactproject/djangoreactproject/urls.py:

      • nano ~/djangoreactproject/djangoreactproject/urls.py

      Deje lo que haya allí, pero añada la importación a las vistas customers en la parte superior del archivo:

      ~/djangoreactproject/djangoreactproject/urls.py

      from django.contrib import admin
      from django.urls import path
      from customers import views
      from django.conf.urls import url
      

      A continuación, añada las URL de api/customers/ y api/customers/<pk> a la lista urlpatterns que contiene las URL de la aplicación:

      ~/djangoreactproject/djangoreactproject/urls.py

      ...
      
      urlpatterns = [
          path('admin/', admin.site.urls),
          url(r'^api/customers/$', views.customers_list),
          url(r'^api/customers/(?P<pk>[0-9]+)$', views.customers_detail),
      ]
      

      Con nuestros puntos finales REST creados, veamos cómo podemos consumirlos.

      Paso 6: consumo de API REST con Axios.

      En este paso, instalaremos Axios, el cliente HTTP que utilizaremos para realizar llamadas de API. También crearemos una clase para consumir los puntos finales de API que hemos creado.

      Primero, desactive su entorno virtual:

      A continuación, navegue a su carpeta frontend:

      • cd ~/djangoreactproject/frontend

      Instale axios desde npm utilizando:

      La opción --save añade la dependencia axios al archivo package.json de su aplicación.

      A continuación, cree un archivo de JavaScript denominado CustomersService.js, que contendrá el código para llamar a las API REST. Realizaremos esto dentro de la carpeta src, donde residirá el código de la aplicación de nuestro proyecto:

      • cd src
      • nano CustomersService.js

      Añada el código siguiente, que contiene métodos para conectarse a la API REST de Django:

      ~/djangoreactproject/frontend/src/CustomersService.js

      import axios from 'axios';
      const API_URL = 'http://localhost:8000';
      
      export default class CustomersService{
      
          constructor(){}
      
      
          getCustomers() {
              const url = `${API_URL}/api/customers/`;
              return axios.get(url).then(response => response.data);
          }  
          getCustomersByURL(link){
              const url = `${API_URL}${link}`;
              return axios.get(url).then(response => response.data);
          }
          getCustomer(pk) {
              const url = `${API_URL}/api/customers/${pk}`;
              return axios.get(url).then(response => response.data);
          }
          deleteCustomer(customer){
              const url = `${API_URL}/api/customers/${customer.pk}`;
              return axios.delete(url);
          }
          createCustomer(customer){
              const url = `${API_URL}/api/customers/`;
              return axios.post(url,customer);
          }
          updateCustomer(customer){
              const url = `${API_URL}/api/customers/${customer.pk}`;
              return axios.put(url,customer);
          }
      }
      

      La clase CustomersService llamará a los siguientes métodos de Axios:

      • getCustomers(): obtiene la primera página de clientes.
      • getCustomersByURL(): obtiene clientes por URL. Esto permite obtener las siguientes páginas de clientes al pasar enlaces como /api/customers/?page=2.
      • get Customer(): obtiene un cliente por clave primaria.
      • createCustomer(): crea un cliente.
      • updateCustomer(): actualiza un cliente.
      • deleteCustomer(): elimina un cliente.

      Ahora, podemos mostrar los datos de nuestra API en nuestra IU de React al crear un componente CustomersList.

      Paso 7: visualización de datos de la API en la aplicación de React

      En este paso, crearemos el componente CustomersList de React. Un componente de React representa una parte de la IU; también le permite dividir la IU en piezas independientes y reutilizables.

      Comience por crear CustomersList.js en frontend/src:

      • nano ~/djangoreactproject/frontend/src/CustomersList.js

      Inicie la importación de React y Component para crear un componente de React:

      ~/djangoreactproject/frontend/src/CustomersList.js

      import  React, { Component } from  'react';
      

      A continuación, importe e instancie el módulo CustomersService que creó en el paso anterior, el cual proporciona métodos que interactúan con el backend de API REST:

      ~/djangoreactproject/frontend/src/CustomersList.js

      
      ...
      import  CustomersService  from  './CustomersService';
      
      const  customersService  =  new  CustomersService();
      

      A continuación, cree un componente CustomersList que extienda Component para llamar a la API REST. Un componente de React debería extender o crear una subclase de la clase Component. Para obtener más información acerca de las clases E6 y herencia, consulte nuestro tutorial sobre Comprensión de las clases de JavaScript.

      Añada el siguiente código para crear un componente de React que extienda react.Component:

      ~/djangoreactproject/frontend/src/CustomersList.js

      
      ...
      class  CustomersList  extends  Component {
      
          constructor(props) {
              super(props);
              this.state  = {
                  customers: [],
                  nextPageURL:  ''
              };
              this.nextPage  =  this.nextPage.bind(this);
              this.handleDelete  =  this.handleDelete.bind(this);
          }
      }
      export  default  CustomersList;
      

      Dentro del constructor, estamos inicializando el objeto state. Este almacena las variables de estado de nuestro componente utilizando una matriz customers vacía. Esta matriz almacenará clientes y una nextPageURL que contendrá la URL de la siguiente página que se obtendrá del back-end de la API. También procedemos a vincular los métodos nextPage() y handleDelete() a this para que sean accesibles desde el código HTML.

      A continuación, añada el método componentDidMount() y una llamada a getCustomers() dentro de la clase CustomersList, antes de la llave de cierre.

      El método componentDidMount() es un método de ciclo de vida del componente que se llama al crear el componente y se inserta en el DOM. getCustomers() llama al objeto Customers Service para obtener la primera página de datos y el enlace de la siguiente página del backend de Django:

      ~/djangoreactproject/frontend/src/CustomersList.js

      
      ...
      componentDidMount() {
          var  self  =  this;
          customersService.getCustomers().then(function (result) {
              self.setState({ customers:  result.data, nextPageURL:  result.nextlink})
          });
      }
      

      Ahora, añada el método handleDelete(), que gestiona la eliminación de un cliente, debajo de componentDidMount():

      ~/djangoreactproject/frontend/src/CustomersList.js

      
      ...
      handleDelete(e,pk){
          var  self  =  this;
          customersService.deleteCustomer({pk :  pk}).then(()=>{
              var  newArr  =  self.state.customers.filter(function(obj) {
                  return  obj.pk  !==  pk;
              });
              self.setState({customers:  newArr})
          });
      }
      

      El método handleDelete() llama al método deleteCustomer() para eliminar un cliente utilizando su pk (clave primaria). Si la operación se realiza correctamente, la matriz customers se filtra por el cliente eliminado.

      A continuación, añada un método nextPage() para obtener los datos de la siguiente página y actualice el enlace de la página siguiente:

      ~/djangoreactproject/frontend/src/CustomersList.js

      
      ...
      nextPage(){
          var  self  =  this;
          customersService.getCustomersByURL(this.state.nextPageURL).then((result) => {
              self.setState({ customers:  result.data, nextPageURL:  result.nextlink})
          });
      }
      

      El método nextPage() llama a un método getCustomersByURL(), que obtiene la URL de la página siguiente del objeto de estado, this.state.nextPageURL, y actualiza la matriz customers con los datos devueltos.

      Por último, añada el método render() del componente, que produce una tabla de clientes del estado de componente:

      ~/djangoreactproject/frontend/src/CustomersList.js

      
      ...
      render() {
      
          return (
          <div  className="customers--list">
              <table  className="table">
                  <thead  key="thead">
                  <tr>
                      <th>#</th>
                      <th>First Name</th>
                      <th>Last Name</th>
                      <th>Phone</th>
                      <th>Email</th>
                      <th>Address</th>
                      <th>Description</th>
                      <th>Actions</th>
                  </tr>
                  </thead>
                  <tbody>
                      {this.state.customers.map( c  =>
                      <tr  key={c.pk}>
                          <td>{c.pk}  </td>
                          <td>{c.first_name}</td>
                          <td>{c.last_name}</td>
                          <td>{c.phone}</td>
                          <td>{c.email}</td>
                          <td>{c.address}</td>
                          <td>{c.description}</td>
                          <td>
                          <button  onClick={(e)=>  this.handleDelete(e,c.pk) }> Delete</button>
                          <a  href={"/customer/" + c.pk}> Update</a>
                          </td>
                      </tr>)}
                  </tbody>
              </table>
              <button  className="btn btn-primary"  onClick=  {  this.nextPage  }>Next</button>
          </div>
          );
      }
      

      Este es el contenido completo del archivo:

      ~/djangoreactproject/frontend/src/CustomersList.js

      import  React, { Component } from  'react';
      import  CustomersService  from  './CustomersService';
      
      const  customersService  =  new  CustomersService();
      
      class  CustomersList  extends  Component {
      
      constructor(props) {
          super(props);
          this.state  = {
              customers: [],
              nextPageURL:  ''
          };
          this.nextPage  =  this.nextPage.bind(this);
          this.handleDelete  =  this.handleDelete.bind(this);
      }
      
      componentDidMount() {
          var  self  =  this;
          customersService.getCustomers().then(function (result) {
              console.log(result);
              self.setState({ customers:  result.data, nextPageURL:  result.nextlink})
          });
      }
      handleDelete(e,pk){
          var  self  =  this;
          customersService.deleteCustomer({pk :  pk}).then(()=>{
              var  newArr  =  self.state.customers.filter(function(obj) {
                  return  obj.pk  !==  pk;
              });
      
              self.setState({customers:  newArr})
          });
      }
      
      nextPage(){
          var  self  =  this;
          console.log(this.state.nextPageURL);        
          customersService.getCustomersByURL(this.state.nextPageURL).then((result) => {
              self.setState({ customers:  result.data, nextPageURL:  result.nextlink})
          });
      }
      render() {
      
          return (
              <div  className="customers--list">
                  <table  className="table">
                  <thead  key="thead">
                  <tr>
                      <th>#</th>
                      <th>First Name</th>
                      <th>Last Name</th>
                      <th>Phone</th>
                      <th>Email</th>
                      <th>Address</th>
                      <th>Description</th>
                      <th>Actions</th>
                  </tr>
                  </thead>
                  <tbody>
                  {this.state.customers.map( c  =>
                      <tr  key={c.pk}>
                      <td>{c.pk}  </td>
                      <td>{c.first_name}</td>
                      <td>{c.last_name}</td>
                      <td>{c.phone}</td>
                      <td>{c.email}</td>
                      <td>{c.address}</td>
                      <td>{c.description}</td>
                      <td>
                      <button  onClick={(e)=>  this.handleDelete(e,c.pk) }> Delete</button>
                      <a  href={"/customer/" + c.pk}> Update</a>
                      </td>
                  </tr>)}
                  </tbody>
                  </table>
                  <button  className="btn btn-primary"  onClick=  {  this.nextPage  }>Next</button>
              </div>
              );
        }
      }
      export  default  CustomersList;
      

      Ahora que hemos creado el componente CustomersList para visualizar la lista de clientes, podemos añadir el componente que gestiona la creación y la actualización de clientes.

      Paso 8: incorporación del componente de React de creación y actualización de clientes

      En este paso, crearemos el componente CustomerCreateUpdate, que se encargará de crear y actualizar clientes. Lo hará al proporcionar una forma que los usuarios puedan utilizar para ingresar datos sobre un cliente nuevo o actualizar una entrada existente.

      En frontend/src, cree un archivo CustomerCreateUpdate.js:

      • nano ~/djangoreactproject/frontend/src/CustomerCreateUpdate.js

      Añada el siguiente código para crear un componente de React, importando React y Component:

      ~/djangoreactproject/frontend/src/CustomerCreateUpdate.js

      import  React, { Component } from  'react';
      

      A continuación, también podemos importar e instanciar la clase CustomersService que creamos en el paso anterior, que proporciona métodos que interactúan con el backend de API REST:

      ~/djangoreactproject/frontend/src/CustomerCreateUpdate.js

      ...
      import  CustomersService  from  './CustomersService';
      
      const  customersService  =  new  CustomersService();
      

      Luego, cree un componente CustomerCreateUpdate que extienda Component para crear y actualizar clientes:

      ~/djangoreactproject/frontend/src/CustomerCreateUpdate.js

      
      ...
      class  CustomerCreateUpdate  extends  Component {
      
          constructor(props) {
              super(props);
          }
      
      }
      export default CustomerCreateUpdate;
      

      Dentro de la definición de clase, añada el método render() del componente, que produce un formulario HTML que toma información sobre el cliente:

      ~/djangoreactproject/frontend/src/CustomerCreateUpdate.js

      
      ...
      render() {
              return (
                <form onSubmit={this.handleSubmit}>
                <div className="form-group">
                  <label>
                    First Name:</label>
                    <input className="form-control" type="text" ref='firstName' />
      
                  <label>
                    Last Name:</label>
                    <input className="form-control" type="text" ref='lastName'/>
      
                  <label>
                    Phone:</label>
                    <input className="form-control" type="text" ref='phone' />
      
                  <label>
                    Email:</label>
                    <input className="form-control" type="text" ref='email' />
      
                  <label>
                    Address:</label>
                    <input className="form-control" type="text" ref='address' />
      
                  <label>
                    Description:</label>
                    <textarea className="form-control" ref='description' ></textarea>
      
      
                  <input className="btn btn-primary" type="submit" value="Submit" />
                  </div>
                </form>
              );
        }
      

      Para cada elemento de entrada del formulario, el método añade una propiedad ref para acceder al valor del elemento del formulario y establecerlo.

      A continuación, por encima del método render(), defina un método handleSubmit(event) de modo que tenga la funcionalidad correcta cuando un usuario haga clic en el botón de enviar:

      ~/djangoreactproject/frontend/src/CustomerCreateUpdate.js

      
      ...
      handleSubmit(event) {
          const { match: { params } } =  this.props;
          if(params  &&  params.pk){
              this.handleUpdate(params.pk);
          }
          else
          {
              this.handleCreate();
          }
          event.preventDefault();
      }
      
      ...
      

      El método handleSubmit(event) gestiona el envío del formulario y, dependiendo de la ruta, llama al método handleUpdate(pk) para actualizar el cliente con la pk correcta, o el método handleCreate() para crear un nuevo cliente. Procederemos a definir estos métodos en breve.

      De nuevo en el constructor del componente, vincule el método handleSubmit() recientemente añadido a this para poder acceder a él en su formulario:

      ~/djangoreactproject/frontend/src/CustomerCreateUpdate.js

      ...
      class CustomerCreateUpdate extends Component {
      
      constructor(props) {
          super(props);
          this.handleSubmit = this.handleSubmit.bind(this);
      }
      ...
      

      A continuación, defina el método handleCreate() para crear un cliente a partir de los datos del formulario. Encima del método handleSubmit(event), añada el siguiente código:

      ~/djangoreactproject/frontend/src/CustomerCreateUpdate.js

      
      ...
      handleCreate(){
          customersService.createCustomer(
              {
              "first_name":  this.refs.firstName.value,
              "last_name":  this.refs.lastName.value,
              "email":  this.refs.email.value,
              "phone":  this.refs.phone.value,
              "address":  this.refs.address.value,
              "description":  this.refs.description.value
              }).then((result)=>{
                      alert("Customer created!");
              }).catch(()=>{
                      alert('There was an error! Please re-check your form.');
              });
      }
      
      ...
      

      El método handleCreate() se utilizará para crear un cliente a partir de los datos ingresados. Llama al método CustomersService.createCustomer() correspondiente que provoca que la API real llame al backend para crear un cliente.

      A continuación, por debajo del método handleCreate(), defina el método handleUpdate(pk) para implementar actualizaciones:

      ~/djangoreactproject/frontend/src/CustomerCreateUpdate.js

      
      ...
      handleUpdate(pk){
      customersService.updateCustomer(
          {
          "pk":  pk,
          "first_name":  this.refs.firstName.value,
          "last_name":  this.refs.lastName.value,
          "email":  this.refs.email.value,
          "phone":  this.refs.phone.value,
          "address":  this.refs.address.value,
          "description":  this.refs.description.value
          }
          ).then((result)=>{
      
              alert("Customer updated!");
          }).catch(()=>{
              alert('There was an error! Please re-check your form.');
          });
      }
      

      El método updateCustomer() actualizará un cliente por pk, utilizando la nueva información del formulario de información de clientes. Llama al método customersService.updateCustomer().

      A continuación, añada un método componentDidMount(). Si el usuario visita una ruta customer/:pk, queremos que el formulario se complete con información relacionada con el cliente utilizando la clave primaria de la URL. Para ello, podemos añadir el método getCustomer(pk) una vez que el componente se monte en el evento de ciclo de vida de componentDidMount(). Añada el siguiente código por debajo del constructor del componente para añadir este método:

      ~/djangoreactproject/frontend/src/CustomerCreateUpdate.js

      
      ...
      componentDidMount(){
          const { match: { params } } =  this.props;
          if(params  &&  params.pk)
          {
              customersService.getCustomer(params.pk).then((c)=>{
                  this.refs.firstName.value  =  c.first_name;
                  this.refs.lastName.value  =  c.last_name;
                  this.refs.email.value  =  c.email;
                  this.refs.phone.value  =  c.phone;
                  this.refs.address.value  =  c.address;
                  this.refs.description.value  =  c.description;
              })
          }
      }
      

      Este es el contenido completo del archivo:

      ~/djangoreactproject/frontend/src/CustomerCreateUpdate.js

      import React, { Component } from 'react';
      import CustomersService from './CustomersService';
      
      const customersService = new CustomersService();
      
      class CustomerCreateUpdate extends Component {
          constructor(props) {
              super(props);
      
              this.handleSubmit = this.handleSubmit.bind(this);
            }
      
            componentDidMount(){
              const { match: { params } } = this.props;
              if(params && params.pk)
              {
                customersService.getCustomer(params.pk).then((c)=>{
                  this.refs.firstName.value = c.first_name;
                  this.refs.lastName.value = c.last_name;
                  this.refs.email.value = c.email;
                  this.refs.phone.value = c.phone;
                  this.refs.address.value = c.address;
                  this.refs.description.value = c.description;
                })
              }
            }
      
            handleCreate(){
              customersService.createCustomer(
                {
                  "first_name": this.refs.firstName.value,
                  "last_name": this.refs.lastName.value,
                  "email": this.refs.email.value,
                  "phone": this.refs.phone.value,
                  "address": this.refs.address.value,
                  "description": this.refs.description.value
              }          
              ).then((result)=>{
                alert("Customer created!");
              }).catch(()=>{
                alert('There was an error! Please re-check your form.');
              });
            }
            handleUpdate(pk){
              customersService.updateCustomer(
                {
                  "pk": pk,
                  "first_name": this.refs.firstName.value,
                  "last_name": this.refs.lastName.value,
                  "email": this.refs.email.value,
                  "phone": this.refs.phone.value,
                  "address": this.refs.address.value,
                  "description": this.refs.description.value
              }          
              ).then((result)=>{
                console.log(result);
                alert("Customer updated!");
              }).catch(()=>{
                alert('There was an error! Please re-check your form.');
              });
            }
            handleSubmit(event) {
              const { match: { params } } = this.props;
      
              if(params && params.pk){
                this.handleUpdate(params.pk);
              }
              else
              {
                this.handleCreate();
              }
      
              event.preventDefault();
            }
      
            render() {
              return (
                <form onSubmit={this.handleSubmit}>
                <div className="form-group">
                  <label>
                    First Name:</label>
                    <input className="form-control" type="text" ref='firstName' />
      
                  <label>
                    Last Name:</label>
                    <input className="form-control" type="text" ref='lastName'/>
      
                  <label>
                    Phone:</label>
                    <input className="form-control" type="text" ref='phone' />
      
                  <label>
                    Email:</label>
                    <input className="form-control" type="text" ref='email' />
      
                  <label>
                    Address:</label>
                    <input className="form-control" type="text" ref='address' />
      
                  <label>
                    Description:</label>
                    <textarea className="form-control" ref='description' ></textarea>
      
      
                  <input className="btn btn-primary" type="submit" value="Submit" />
                  </div>
                </form>
              );
            }  
      }
      
      export default CustomerCreateUpdate;
      

      Con el componente CustomerCreateUpdate creado, podemos actualizar el componente principal App para añadir enlaces a los diferentes componentes que hemos creado.

      Paso 9: actualización del componente principal App

      En esta sección, actualizaremos el componente App de nuestra aplicación para crear enlaces a los componentes que hemos creado en los pasos anteriores.

      Desde la carpeta frontend, ejecute el siguiente comando para instalar React Router, que le permite añadir enrutamiento y navegación entre varios componentes de React:

      • cd ~/djangoreactproject/frontend
      • npm install --save react-router-dom

      A continuación, abra ~/djangoreactproject/frontend/src/App.js:

      • nano ~/djangoreactproject/frontend/src/App.js

      Elimine todo lo que haya allí y añada el siguiente código para importar las clases necesarias para incorporar enrutamiento. Estas incluyen BrowserRouter, que crea un componente Router, y Route, que crea un componente de ruta:

      ~/djangoreactproject/frontend/src/App.js

      import  React, { Component } from  'react';
      import { BrowserRouter } from  'react-router-dom'
      import { Route, Link } from  'react-router-dom'
      import  CustomersList  from  './CustomersList'
      import  CustomerCreateUpdate  from  './CustomerCreateUpdate'
      import  './App.css';
      

      BrowserRoutermantiene la IU sincronizada con la URL utilizando la ](https://developer.mozilla.org/en-US/docs/Web/API/History_API)API de historial HTML5[.

      A continuación, cree un diseño base que proporcione el componente básico que envolverá el componente BrowserRouter:

      ~/djangoreactproject/frontend/src/App.js

      ...
      
      const  BaseLayout  = () => (
      <div  className="container-fluid">
          <nav  className="navbar navbar-expand-lg navbar-light bg-light">
              <a  className="navbar-brand"  href="https://www.digitalocean.com/#">Django React Demo</a>
              <button  className="navbar-toggler"  type="button"  data-toggle="collapse"  data-target="#navbarNavAltMarkup"  aria-controls="navbarNavAltMarkup"  aria-expanded="false"  aria-label="Toggle navigation">
              <span  className="navbar-toggler-icon"></span>
          </button>
          <div  className="collapse navbar-collapse"  id="navbarNavAltMarkup">
              <div  className="navbar-nav">
                  <a  className="nav-item nav-link"  href="/">CUSTOMERS</a>
                  <a  className="nav-item nav-link"  href="http://www.digitalocean.com/customer">CREATE CUSTOMER</a>
              </div>
          </div>
          </nav>
          <div  className="content">
              <Route  path="/"  exact  component={CustomersList}  />
              <Route  path="/customer/:pk"  component={CustomerCreateUpdate}  />
              <Route  path="/customer/"  exact  component={CustomerCreateUpdate}  />
          </div>
      </div>
      )
      

      Utilizamos el componente Route para definir las rutas de nuestra aplicación; el componente que el enrutador debe cargar cuando se encuentra una coincidencia. Cada ruta requiere un path que especifique la ruta que se debe seguir y un component que indique el componente que se debe cargar. La propiedad exact le indica al enrutador que siga la trayectoria exacta.

      Por último, cree el componente App, el componente root o de nivel superior de nuestra aplicación de React:

      ~/djangoreactproject/frontend/src/App.js

      ...
      
      class  App  extends  Component {
      
      render() {
          return (
          <BrowserRouter>
              <BaseLayout/>
          </BrowserRouter>
          );
      }
      }
      export  default  App;
      

      Hemos envuelto el componente BaseLayout con el componente BrowserRouter, dado que nuestra aplicación está diseñada para ejecutarse en un navegador.

      El archivo completo se ve de este modo:

      ~/djangoreactproject/frontend/src/App.js

      import React, { Component } from 'react';
      import { BrowserRouter } from 'react-router-dom'
      import { Route, Link } from 'react-router-dom'
      
      import  CustomersList from './CustomersList'
      import  CustomerCreateUpdate  from './CustomerCreateUpdate'
      import './App.css';
      
      const BaseLayout = () => (
        <div className="container-fluid">
      <nav className="navbar navbar-expand-lg navbar-light bg-light">
        <a className="navbar-brand" href="https://www.digitalocean.com/#">Django React Demo</a>
        <button className="navbar-toggler" type="button" data-toggle="collapse" data-target="#navbarNavAltMarkup" aria-controls="navbarNavAltMarkup" aria-expanded="false" aria-label="Toggle navigation">
          <span className="navbar-toggler-icon"></span>
        </button>
        <div className="collapse navbar-collapse" id="navbarNavAltMarkup">
          <div className="navbar-nav">
            <a className="nav-item nav-link" href="/">CUSTOMERS</a>
            <a className="nav-item nav-link" href="http://www.digitalocean.com/customer">CREATE CUSTOMER</a>
      
          </div>
        </div>
      </nav>  
      
          <div className="content">
            <Route path="/" exact component={CustomersList} />
            <Route path="/customer/:pk"  component={CustomerCreateUpdate} />
            <Route path="/customer/" exact component={CustomerCreateUpdate} />
      
          </div>
      
        </div>
      )
      
      class App extends Component {
        render() {
          return (
            <BrowserRouter>
              <BaseLayout/>
            </BrowserRouter>
          );
        }
      }
      
      export default App;
      

      Ahora que añadimos enrutamiento a nuestra aplicación, estamos listos para probarla. Navegue a http://localhost:3000. Debería ver la primera página de la aplicación:

      Página de inicio de la aplicación

      Con la implementación de esta aplicación, ahora, cuenta con la base para una aplicación de CRM.

      Conclusión

      En este tutorial, usted creó una aplicación de prueba utilizando Django y React. Utilizó Django REST framework para crear la API REST, Axios para consumir la API y Bootstrap 4 para dar estilo a su CSS. Puede encontrar el código fuente de este proyecto en este repositorio de GitHub.

      En la configuración de este tutorial, se utilizaron aplicaciones de front-end y back-end. Para obtener un enfoque diferente de la integración de React con Django, consulte este tutorial y este otro tutorial.

      Para obtener más información sobre la creación de aplicaciones con Django, puede seguir la serie de desarrollo de Django. También puede consultar la documentación oficial de Django.



      Source link