How to set up Vue.js with Django
Getting Vue.js and Django to work together can be challenging, especially when sychronising the build .js
files from Vue with the static folder in Django. There are various ways to go about it. The most popular of methods utilise the django-webpack-loader
, where the Django library identifies the build files created by the Vue project. Here we are going to try a different approach, one that requires just a tiny amount of tinkering to get your Django + Vue
project up and running.
#Installing Django
Before we install Django, we will set up a virtual environment for our Django project. Access the directory of your choice using the command line interface. With the cmd line we will create a new directory called djangovue
and change to it.
mkdir djangovue cd djangovue
To create a virtual environment, we will run the command python -m venv <name of your choice>
. For this tutorial we will name our virtual environment env
.
python -m venv env
This creates an env
folder with our virtual environment settings. To activate our virtual environment, we will need to access the activate script which resides in the directory env/Scripts/
. In the cmd line type
env\Scripts\activate
and you should see (env)
prepended to your project directory like below.
(env) C:\djangovue>
Next we will install Django itself by running the command
pip install django
With django now installed, let's create a django project by entering the command
django-admin startproject djangosite
Now we have a folder called djangosite. The folder structure should look something like this.
|-env |-djangosite |-djangosite |-manage.py
Change directory to the djangosite with cd djangosite
and run the command python manage.py runserver
, which will run django's development server. Visit the url http://127.0.0.1:8000/
or http://localhost:8000/
and we have our django website running.
#Installing Vue.js
Creating a Vue.js project will be slightly simpler. Open another cmd
window for handling node.js
operations. We will first install vue-cli
with the command:
npm install -g @vue/cli
In our root djangovue
folder, we will create our Vue project by running:
vue create vuesite
We will go with the default configuration. After the project is created, enter command cd vuesite
and run npm run serve
. Our vue side of the project will be available to us at http://localhost:8080/
. The folder structure for reference looks like this.
|-env |-djangosite |-vuesite
#Configuring The Django Side
Now, our aim will be to get the front-page from http://localhost:8080/
(vue side) to show up in http://localhost:8000/
(django side).
Create a templates
folder in djangosite
. And then add an index.html
file inside the newly created templates
folder.
|-env |-djangosite |-djangosite |-settings.py |-templates |-index.html |-vuesite
And in settings.py
, configure your template settings by adding the location of your templates folder.
TEMPLATES = [ { 'BACKEND': 'django.template.backends.django.DjangoTemplates', 'DIRS': [os.path.join(BASE_DIR, 'templates')], # add this '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', ], }, }, ]
We will also create a directory for static files called static
, which will house the build files from the Vue project. Django will look for the javascript
files here.
|-env |-djangosite |-djangosite |-settings.py |-urls.py |-templates |-static |-vuesite
Again, in the settings.py
file we will tell Django the location of the static
directory. At the end of the settings.py
file add:
STATIC_URL = '/static/' # add this below STATIC_URL STATICFILES_DIRS = [os.path.join(BASE_DIR, "static")]
In urls.py, we will add a generic template view for our home page.
from django.contrib import admin from django.urls import path # add this from django.views.generic import TemplateView urlpatterns = [ path('admin/', admin.site.urls), # add this path("", TemplateView.as_view(template_name='index.html')), ]
Let's add some content to our index.html
file.
<!DOCTYPE html> <html lang="en"> <head> <meta charset="UTF-8"> <meta name="viewport" content="width=device-width, initial-scale=1.0"> <meta http-equiv="X-UA-Compatible" content="ie=edge"> <title>Document</title> </head> <body> <p>We have created an Index.html page.</p> </body> </html>
When you now visit the url http://localhost:8000/
, we should see the above content from index.html
.
#Configuring The Vue Side
While working on the development end of Vue projects, there's a lot of abstraction and unless one goes looking, the .js
files that run our project are hidden. They are, however, available to you in the dist
folder, when you run the command npm run build
.
What we need to do is to move these files to the static
folder inside the djangosite directory. For that, we will create a vue.config.js
file in the vuesite
directory.
|-env |-djangosite |-vuesite |-dist |-node_modules |-public |-src |-package.json |-vue.config.js // create this file
Inside the vue.config.js
file, we will direct Vue to place the build files in a folder of our choice.
module.exports = { outputDir: '../djangosite/static', }
The ..
means we go a directory up to the root, make our way to djangosite
and then to the static
folder. Let's run the command npm run build
again. And voila, we have build files from the vuesite
in our static
folder over at the djangosite
. However, running npm run build
on every save isn't very ideal. What if we could watch for the save and then trigger the creation of a build file on every ctrl + s
action? For that, we have a handy little vue-plugin called vue-cli-plugin-build-watch
.
To install the plugin, run vue add vue-cli-plugin-build-watch
and then start your app with npm run build-watch
. The plugin will create a single app.js
file on every save. If you are using vue-router
, there will be code-splitting based on router components (code splitting is advised in production, but you can comment it out during development - settings available in router.js).
#Making It Work
In the templates/index.html
file over at djangosite
, we will make the following edits
<div id="app"> </div> {% load static %} <script src="{% static 'app.js' %}"></script> <!-- or just --> <script src="/static/app.js"></script>
In the vuesite/src/App.vue
file, we will make a few edits to make sure things are working properly.
<template> <div class="home"> <img alt="Vue logo" src="../assets/logo.png"> <!-- delete this line --> <HelloWorld msg="I'm building a Django + Vue.js application."/> <!-- edit this line --> </div> </template>
Reload the url http://localhost:8000
and the edit from the Vue.js project should reflect on the django side.
And there you should have it, your project's Vue.js and Django parts are in sync. Happy coding!