Como integrar Django 3 con Vue 3 y no morir en el intento
Hola amigos de CodigoJS, Desarrollo web en Sevilla, hoy os comparto un post súper interesante sobre como integrar dos tecnologías punteras en el desarrollo web para afrontar proyectos de cualquier alcance.
Hasta hace poco la mayoría de los proyectos utilizaban en el frontend JQuery para hacer la web más interactiva. La llegada de frameworks JS como React y VueJS ha facilitado el desarrollo de la web, permitiéndonos hacer sitios web más robustos y atractivos.
Lo anterior me ha llevado a desarrollar este tutorial que explica cómo integrar Django 3 y VueJS 3 en el siguiente escenario:
Supongamos que el proyecto que vamos a desarrollar es crítico para SEO y que somos fans de Django, queremos cubrir todo lo relacionado con JavaScript utilizando VueJS. Por tanto, utilizaríamos Vue en formularios de reservas que interactúan con el backend, etc…
Esta integración nos va ha permitir escribir los componentes de Vue utilizando todas las facilidades que nos ofrecen los Componentes de un Solo Archivo (Single File Components) y compilarlos para que todos los navegadores los puedan leer sin ningún tipo de problema.
Crear un Proyecto Django 3
Lo primero que haremos será crear un nuevo proyecto con Django 3. Nos vamos a la consola y escribimos los siguientes comandos para crear el directorio de nuestro proyecto:
$ mkdir django-vue
$ cd django-vue
Entorno virtual Python
El próximo paso es crear un entrono virtual para Python.
$ python3 -m venv venv
Después lo activamos
$ source venv/bin/activate
y por último comenzamos a instalar Django en su última versión
$ pip install django
Crear proyecto Django 3
Ahora vamos a crear un nuevo proyecto con Django 3 con el nombre djvue
$ django-admin startproject djvue
accedemos a la carpeta del proyecto
$ cd djvue
ejecutamos las migraciones de la base de datos
$ python manage.py migrate
de esta forma ya podemos correr nuestro servidor de desarrollo en Django
$ python manage.py runserver
por último nos vamos al navegador y cargamos la siguiente url: http://localhost:8000 donde podremos ver la página inicial del proyecto.
Instalar django-webpack-loader
El siguiente paso, es instalar django-webpack-loader el cual inyecta en nuestras plantillas html de Django los js y css generados por Vue3. Para entendenrlo un poco mejor, esta app actúa como intermediario entre Django y Vue.
$ pip install django-webpack-loader,
Configurar el proyecto Django
Ahora vamos a modificar nuestro proyecto para establecer la configuración de django-webpack-loader y los archivos estáticos. Para ello editamos el archivo settings.py de nuestro proyecto y establecemos las siguientes configuraciones.
En el top del archivo importamos el modulo os de python
import os
En la sección del INSTALLED_APPS añadimos ‘webpack_loader’, para que active la aplicación recién instalada.
INSTALLED_APPS = [
'django.contrib.admin',
'django.contrib.auth',
'django.contrib.contenttypes',
'django.contrib.sessions',
'django.contrib.messages',
'django.contrib.staticfiles',
'webpack_loader',
]
En la sección de TEMPLATES donde está la clave ‘DIRS’: [], la actualizamos para que quede de la siguiente forma:
TEMPLATES = [
{
'BACKEND': 'django.template.backends.django.DjangoTemplates',
'DIRS': [os.path.join(BASE_DIR, 'templates/')], # Establecemos el directorio de las plantillas
'APP_DIRS': True,
'OPTIONS': {
'context_processors': [
'django.template.context_processors.debug',
'django.template.context_processors.request',
'django.contrib.auth.context_processors.auth',
'django.contrib.messages.context_processors.messages',
],
},
},
]
A continuación nos vamos a la raíz de nuestro proyecto y creamos el directorio templates
Seguimos ahora con la configuración de los archivos estáticos de Django. Nos vamos al final del archivo y debajo de STATIC_URL añadimos las siguientes opciones.
STATIC_URL = '/static/'
STATIC_ROOT = os.path.join(BASE_DIR, 'public/static/')
MEDIA_URL = '/media/'
MEDIA_ROOT = os.path.join(BASE_DIR, 'public/media/')
STATICFILES_DIRS = (
os.path.join(BASE_DIR, 'public/static_dev/'),
os.path.join(BASE_DIR, "ui/dist"), # Bundle de VUE
)
Aquí lo más importante es destacar el directorio ui/dist en el cual se va a generar el bundle o archivos estáticos del proyecto Vue3 que veremos más adelante.
Ahora vamos a crear la configuración de webpack-loader, el cual como dije anteriormente será el encargado de inyectar los archivos estáticos js y css generados por Vue en nuestras plantillas html.
# Directorio de Vue
UI_DIR = os.path.join(BASE_DIR, 'ui/')
# Opciones de webpack-loader
WEBPACK_LOADER = {
'DEFAULT': {
'CACHE': not DEBUG,
'BUNDLE_DIR_NAME': 'webpack_bundles/',
'STATS_FILE': os.path.join(UI_DIR, 'webpack-stats.json'),
'POLL_INTERVAL': 0.1,
'TIMEOUT': None,
'IGNORE': [r'.+\.hot-update.js', r'.+\.map'],
'LOADER_CLASS': 'webpack_loader.loader.WebpackLoader',
}
}
Lo más importante a destacar aquí en la clave STATS_FILE, en la que se guarda el fichero donde se van a mapear los archivos del bundle de Vue3. Este archivo se genera de forma automática así que no tenemos que hacer nada.
Listo, hasta aquí todas las configuraciones de Django. Antes de continuar, vamos a guardar todos los cambios y ejecutar el proyecto para comprobar que todo está bien.
Instalación de Vue3
Lo primero que debemos comprobar es si tenemos node instalado, nos vamos a la consola y ejecutamos el siguiente comando:
$ node -v
v12.20.0
En mi caso tengo la versión 12.20.0. Si no tienes node instalado, vamos a la consola y lo instalamos con el siguiente comando:
$ sudo apt install nodejs
Si quieres instalar la última versión o alguna en específico te recomiendo este tutorial de Digital Ocean.
Una vez comprobado que tenemos node instalado, procedemos a instalar Vue.
Para instalar VueJS 3 vamos a utilizar Vue CLI, que no es nada más que una herramienta de node que nos permite crear fácilmente un nuevo proyecto. Por tanto lo primero que debemos instalar es Vue CLI de forma global, para todo el sistema.
$ npm install -g @vue/cli
Crear proyecto Vue3
El proyecto de Vue los vamos a crear en la raiz del proyecto de Django, con el nombre ui (user interface). Nos vamos a la consola y ejecutamos
$ vue create ui
Vue CLI nos preguntará por la versión de queremos instalar.
Seleccionamos la opción. Default, como se ve en la imagen para instalar Vue 3, presionamos enter y esperamos a que el proceso termine.
Una vez terminado accedemos al directorio de proyecto como sugiere la ayuda del instalador.
$ cd ui
y para comprobar que todo ha ido bien, ejecutamos el servidor de desarrollo de Vue3
$ npm run serve
abrimos el navegador y cargamos la url http://localhost:8080/
Llegado a este punto debemos saber, que para la ejecución de este proyecto, debemos tener dos terminales abiertas, una con el proyecto de Django y otra con Vue.
Configurar Vue3
Necesitamos establecer algunas configuraciones antes de continuar. Lo primero es instalar el paquete de node webpack-bundle-tracker, que hará un seguimiento de los archivos estáticos generados por Vue en el archivo webpack-stats.json, el cual añadimos anteriormente en la configuración de Django. Dicho esto lo instalamos desde la terminal.
$ npm install --save-dev webpack-bundle-tracker@0.4.3
Importante: En el momento que se escribe este tutorial, debemos instalar la versión 0.4.3 que es la última estable, si instalamos la última versión, que está en el canal alpha no va a funcionar. Así que tened en cuenta este punto.
Una vez finalizada la instalación del paquete, vamos crear la configuración de Vue, para que nos permita crear el bundle o archivos estáticos js y css para que Django los pueda leer e insertarlos en las plantillas html.
En el directorio ui creamos un archivo llamado vue.config.js y le añadimos el siguiente contenido:
// Importamos webpack-bundle-tracker
const BundleTracker = require("webpack-bundle-tracker");
module.exports = {
// La ruta donde estará disponible el bundle de los archivos estáticos
publicPath: "http://0.0.0.0:8080/",
// Directorio donde se creará el bundle de archivos estáticos
outputDir: './dist/',
// Estable que se compile en tiempo de ejecución.
runtimeCompiler: true,
// Los puntos de entrada de nuestra aplicación.
pages: {
main: {
// entry for the page
entry: 'src/main.js',
},
},
chainWebpack: config => {
config.optimization
.splitChunks(false)
config
.plugin('BundleTracker')
// El archivo que mapeará los estáticos del proyecto.
.use(BundleTracker, [{filename: './webpack-stats.json'}])
config.resolve.alias
.set('__STATIC__', 'static')
config.devServer
.public('http://0.0.0.0:8080')
.host('0.0.0.0')
.port(8080)
.hotOnly(true)
.watchOptions({poll: 1000})
.https(false)
.headers({"Access-Control-Allow-Origin": ["\*"]})
}
};
Este archivo es sumamente importante, he comentado las opciones más relevantes, si quieres profundizar te recomiendo echarle un ojo a la documentación.
Crear un vista en Django.
Nos vamos a la consola de Django, para crear una app donde incluiremos nuestros componentes de Vue3
$ python manage.py startapp index
Editamos el archivo de configuración settings.py y la añadimos a las INSTALLED_APPS
INSTALLED_APPS = [
'django.contrib.admin',
'django.contrib.auth',
'django.contrib.contenttypes',
'django.contrib.sessions',
'django.contrib.messages',
'django.contrib.staticfiles',
'webpack_loader',
'index.apps.IndexConfig',
]
Editamos el archivo views.py de la app index y creamos una vista tan sencilla como esta.
from django.shortcuts import render
def index(request):
context = {}
return render(request, 'index.html', context)
Ahora necesitamos crear la plantilla index.html. En la misma aplicación index, creamos un directorio llamado templates y después otra llamada index, y dentro de esta última el archivo index.html, como se puede ver a continuación:
Editamos la plantilla y añadimos algo de contenido
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>Integrar Django 3 y Vue 3</title>
</head>
<body>
<h1 style="text-align: center;">Como integrar Django 3 y VueJS 3</h1>
</body>
</html>
Ahora toca definir la url de nuestra vista. Primero vamos a crear el archivo urls.py dentro de la app index con el siguiente contenido:
from django.shortcuts import render
def index(request):
context = {}
return render(request, 'index/index.html', context)
Seguido definimos nuestra url dentro de la aplicacion index. Creamos un archivo llamos urls.py dentro de la app index con el siguiente contenido:
from django.urls import path
from . import views
urlpatterns = [
path('', views.index, name='index'),
]
y por último incluimos las rutas de la aplicación index en el archivo urls.py principal de nuestro proyecto: djvue -> urls.py con el siguiente contenido:
from django.contrib import admin
from django.urls import path, include
urlpatterns = [
path('admin/', admin.site.urls),
path('', include('index.urls')),
]
Listo, ahora ya podemos recargar la página y comprobar que se ha cargado nuestra vista.
Inyectar VueJS en las plantillas HTML Ya estamos llegando al final. Ahora vamos decirle a Django como insertar nuestros componentes de Vue en las plantillas html.
Editamos la plantilla index.html y añadimos el siguiente templatetags.
{% load render_bundle from webpack_loader %}
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>Integrar Django 3 y Vue 3</title>
</head>
<body>
<h1 style="text-align: center;">Como integrar Django 3 y VueJS 3</h1>
{% render_bundle 'main' %}
</body>
</html>
Al principio cargamos el template tag render_bundle y al final, antes de cerrar el body insertamos el bundle main, que corresponde al archivo main.js que tenemos declarado en el archivo de vue.config.js, especificamente en esta sección:
...
// Los puntos de entrada de nuestra aplicación.
pages: {
main: {
// entry for the page
entry: 'src/main.js',
},
},
...
Para comprobar que todo está funcionando bien, recargamos la página y pulsamos ctrl + u para ver código fuente:
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>Integrar Django 3 y Vue 3</title>
</head>
<body>
<h1 style="text-align: center;">Como integrar Django 3 y VueJS 3</h1>
<script type="text/javascript" src="http://0.0.0.0:8080/js/main.js" ></script>
</body>
</html>
Si nos fijamos, antes del body se está cargando el archivo main.js desde el servidor de desarrollo de Vue que debemos tener en ejecución en otra terminal. Si hacemos clic en http://0.0.0.0:8080/js/main.js podemos ver su contenido…
Guay!!!!! estamos a un pelín de lograrlo
Pintando el primer componente
Editamos el archivo src/main.js que es el punto de entrada de nuestra aplicación Vue con el siguiente contenido.
import { createApp, ref } from 'vue'
// Importamos el componente HelloDjango
import HelloDjango from './components/HelloDjango'
// Creamos una instancia de la aplicación Vue
const app = createApp({
// Elemento html donde se va ha renderizar el contenido
el: '#app',
// Cambiamos los delimiters de las variables para que sean diferentes a los de Django
delimiters: ['[[', ']]'],
// Activamos el componente dentro de la app
components : {
HelloDjango
},
// Creamos variable msg reactiva con ref
data () {
return {
msg: ref('Componente de VueJS 3')
}
},
})
// Montamos la app en el div #app de nuestra plantilla index.html.
app.mount('#app')
Creamos el componente HelloDjango.vue dentro de la carpeta src/components con el siguiente contenido
<template>
<div style="color: red;">Este el primer componente de Vue3 insertado en Django 3</div>
</template>
<script>
export default {
name: 'HelloDjango',
}
</script>
<style scoped>
</style>
Por último editamos nuevamente el archivo index.html de Django e insertamos un div debajo del h1 con el siguiente contenido:
...
<div id="app" style="text-align: center;">
[[ msg ]]
<hello-django/>
</div>
...
...
Aquí estamos creando el punto de montaje de nuestra aplicación de Vue al establecer el id=“app”
[[ msg ]] es la variable que creamos en el data utilizando los delimiters [] para no crear conflictos con Django.
Conclusiones
Hemos visto como integrar Django3 y Vue3 para hacer una web amigable para el SEO y totalmente dinámica utilizando las tecnologías actualizadas.
¿Que más podríamos hacer? Pues todo lo que se nos ocurra:
Montar una web con Django3, Vue3 y Bulma o Tailwind CSS Integrar Django Rest Framework en el backend y crear componentes totalmente dinámicos con Vue como formulario de reservas, sliders, etc… En fin con esta combinación de tecnologías podemos desarrollar proyecto de cualquier alcance.