Skip to content

Instantly share code, notes, and snippets.

@8area8
Last active September 21, 2021 15:40
Show Gist options
  • Save 8area8/ba3e747bc1693fc99fc7bbba209c6a20 to your computer and use it in GitHub Desktop.
Save 8area8/ba3e747bc1693fc99fc7bbba209c6a20 to your computer and use it in GitHub Desktop.
Django/Vue-cli coupling

Basic workflow to Django/Vue-cli coupling

The goal of this workflow is to couple vue-cli to Django, in a transparent way in dev and in prod. The hot-reload is active in the backend as well as in the frontend, and the frontend is accessed through Django, from the index page ;)

Note: We also use the router's historical mode, for a more professional integration.

Note²: Do not forget to build the vue-cli project for production!

Base

python3 -m venv .venv
. .venv/bin/activate
pip install black flake8 pylint pydocstyle mypy  # best linters/formatter

Add Django and DRF

pip install django djangorestframework
pip freeze > requirments.txt
django-admin startproject back .
mkdir back/apps && touch back/apps/__init__.py
mkdir back/assets && touch back/assets/README.md # be sure to be tracked by git

Add vue-cli

(install vue-cli as global dependency)

vue create front # use vue-cli 3
cd front && touch vue.config.js  # create the conf file
npm i -D clean-webpack-plugin vue-router@next # get the router

Configuration

Configure vue-cli

vue.config.js

/*eslint-disable */
const { CleanWebpackPlugin } = require("clean-webpack-plugin");

module.exports = {
  publicPath: "static/",
  configureWebpack: {
    devServer: {
      writeToDisk: true, // used to link the webpack server to Django
    },
    plugins: [new CleanWebpackPlugin()],
  },
};

NOTE: the following is based on this tutorial to implement vue-router to vue-cli 3.

front/src/main.js

import { createApp } from 'vue'
import App from './App.vue'
import router from './router'

createApp(App).use(router).mount('#app')

front/src/router/index.js

import { createWebHistory, createRouter } from "vue-router";
import Home from "@/views/Home.vue";
import About from "@/views/About.vue";

const routes = [
  {
    path: "/",
    name: "Home",
    component: Home,
  },
  {
    path: "/about",
    name: "About",
    component: About,
  },
];

const router = createRouter({
  history: createWebHistory(),
  routes,
});

export default router;

front/src/apps.vue

<template>
<div>

  <div id="nav">
      <router-link to="/">Home</router-link> |
      <router-link to="/about">About</router-link>
  </div>
  <router-view />
</div>
</template>

<script>

export default {
  name: 'App',
}
</script>

<style>
#app {
  font-family: Avenir, Helvetica, Arial, sans-serif;
  -webkit-font-smoothing: antialiased;
  -moz-osx-font-smoothing: grayscale;
  text-align: center;
  color: #2c3e50;
  margin-top: 60px;
}
</style>

front/src/views/Home.vue

<template>
  <h1>Home Page</h1>
</template>

front/src/views/About.vue

<template>
  <h1>About Page</h1>
</template>

Configure Django

settings.py

# ...

VUE_DIST = BASE_DIR / "front" / "dist"
ASSETS_DIR = BASE_DIR / "back" / "assets"

# ...

TEMPLATES = [
    {
        "BACKEND": "django.template.backends.django.DjangoTemplates",
        "DIRS": [VUE_DIST],  # get "index.html" in vue-cli dist
        "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",
            ],
        },
    },
]

# ...

STATIC_URL = "/static/"  # check the default value
STATICFILES_DIRS = [VUE_DIST, ASSETS_DIR]  # link to the vue-cli dist folder
STATIC_ROOT = BASE_DIR / "staticfiles"  # check the default value

# ...

urls.py

# ...

from django.contrib import admin
from django.urls import path, include, re_path
from django.views.generic import TemplateView


urlpatterns = [
    path("admin/", admin.site.urls),
    # vuejs
    re_path(r"^.*", TemplateView.as_view(template_name="index.html")),
]

Enjoy

the coupling is complete; you should be able to connect to the Django server, and access the VueJS application :)

@smudge1977
Copy link

requirments.txt is what you want next
pip freeze > requirments.txt
pip install -r requirments.txt
put the requirments.txt in your repo and then when you clone you do as above and pip install to install what you have in requirments.txt

@8area8
Copy link
Author

8area8 commented Sep 17, 2021

yep thx I ll add it ;)

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment