Django is a python web development framework that was initially released in 2005. It will be of no surprise that there are django projects as old as 10 years, some of us might have even inherited such projects. The method shown in this tutorial is proven to work on Django 1.8 and above. Little modifications might be necessary for a lower version of Django.
This integration will be making use of a js package, laravel-mix which is used in the Laravel project for integrating Vue.
Enough said, let’s get stuff done.
Assuming your project has the following structure;
--django-project --django-project settings.py urls.py --static --templates base.html
You should first create a package.json file in our project directory, and it should have the following content
{ "private": true, "scripts": { "dev": "npm run development", "development": "cross-env NODE_ENV=development node_modules/webpack/bin/webpack.js --progress --hide-modules --config=node_modules/laravel-mix/setup/webpack.config.js", "watch": "npm run development -- --watch", "watch-poll": "npm run watch -- --watch-poll", "hot": "cross-env NODE_ENV=development node_modules/webpack-dev-server/bin/webpack-dev-server.js --inline --hot --config=node_modules/laravel-mix/setup/webpack.config.js", "prod": "npm run production", "production": "cross-env NODE_ENV=production node_modules/webpack/bin/webpack.js --no-progress --hide-modules --config=node_modules/laravel-mix/setup/webpack.config.js" }, "devDependencies": { "axios": "^0.19", "bootstrap": "^4.0.0", "cross-env": "^6.0", "jquery": "^3.2", "laravel-mix": "^5.0.1", "lodash": "^4.17.13", "popper.js": "^1.12", "resolve-url-loader": "^2.3.1", "sass": "^1.20.1", "sass-loader": "7.*", "vue": "^2.5.17", "vue-template-compiler": "^2.6.10" }, }
This contains the necessary dependencies to get you up and running. After creating this file, you can now run yarn install
or npm install
depending on what package manager you use.
In your project directory, create a resources folder, it should have the following structure;
--resources/ --js/ --components/ app.js bootstrap.js --sass app.scss
Next, you have to create a webpack.mix.js
file in your project directory with the following content;
const mix = require('laravel-mix'); mix.js('resources/js/app.js', 'assets/js/vue-app.js') .sass('resources/sass/app.scss', 'assets/css/vue-app.css');
The code in this file takes the app.js
file in the resources directory, processes it and places the compiled js file into vue-app.js
, same with the app.scss
file. The assumption made here is that the assets
folder is one of the places python manage.py collectstatic
looks for static files.
You need to place some code into our app.js
and bootstrap.js
file
app.js
require('./bootstrap'); window.Vue = require('vue'); /** * The following block of code may be used to automatically register your * Vue components. It will recursively scan this directory for the Vue * components and automatically register them with their "basename". * * Eg. ./components/ExampleComponent.vue -> <example-component></example-component> */ // const files = require.context('./', true, /\.vue$/i) // files.keys().map(key => Vue.component(key.split('/').pop().split('.')[0], files(key).default)) Vue.component('example-component', require('./components/ExampleComponent.vue').default); /** * Next, we will create a fresh Vue application instance and attach it to * the page. Then, you may begin adding components to this application * or customize the JavaScript scaffolding to fit your unique needs. */ const app = new Vue({ el: '#app', });
Components that you create are registered in this file using the syntax
Vue.component('example-component', require('./components/ExampleComponent.vue').default);
This means that the component, ExampleComponent
will be rendered in your HTML using the markup <example-component></example-component>
bootstrap.js
window._ = require('lodash'); /** * We'll load jQuery and the Bootstrap jQuery plugin which provides support * for JavaScript based Bootstrap features such as modals and tabs. This * code may be modified to fit the specific needs of your application. */ try { window.Popper = require('popper.js').default; window.$ = window.jQuery = require('jquery'); require('bootstrap'); } catch (e) {} /** * We'll load the axios HTTP library which allows us to easily issue requests * to our Laravel back-end. This library automatically handles sending the * CSRF token as a header based on the value of the "XSRF" token cookie. */ window.axios = require('axios'); window.axios.defaults.headers.common['X-Requested-With'] = 'XMLHttpRequest';
You can now create a sample component in resources/js/components
. You should name the file ExampleComponent.vue
ExampleComponent.vue
<template> <div class="container"> <div class="row justify-content-center"> <div class="col-md-8"> <div class="card"> <div class="card-header">Example Component</div> <div class="card-body"> I'm an example component. </div> </div> </div> </div> </div> </template> <script> export default { mounted() { console.log('Component mounted.') } } </script>
So how do you bring all of this into your django app? Remember you created a base.html
file in your templates directory. This is assuming that other templates inherit from the base.html
file, or in other words, base.html
is a layout file.
So your base.html file looks this way
<!DOCTYPE html> <html> <head> <title>Django vue</title> </head> <body> <div id="app"> {% block body %} {% endblock %} </div> <script src="{% static 'js/vue-app.js' %}"></script> </body> </html>
Lets now create an index.html file
{% extends 'base.html' %} {% block body %} <example-component></example-component> {% endblock %}
ExampleComponent
will be rendered where <example-component></example-component>
is placed.
The assumption made here is that your index route does this return render(request, 'index.html')
or in some other way, renders the index.html page
To get all of this cooked up and ready for consumption, run npm run dev
or yarn run dev
in the command line, depending on what package manager you use. This will compile your vue components into a js file.
Now go to your browser and visit your index url, you should have this nicely displayed
The bundle size of the vue-app.js
file might be a bit large. You should consider removing imports that you do not need.
Also remember to add node_modules/
to your .gitignore
file
Disclaimer: Most of the code written here was not created by me, they were taken from the Laravel project and adapted to work in django with little modifications. I claim no ownership to the code.