Hooking up Django and Vue.js

This article is for individuals who have had intermediate practice with the Vue.js and Django separately, but need direction on how to make these two frameworks work together. I will outline an example of how to set up some boilerplate code with a straightforward project structure using Django and Vue.js. Please note I am developing on macOS Catalina, so the shell commands will vary for your operating system. The finished product can be found on my github: https://github.com/jordanengstrom/blank_django_vue_project

At a high level we will be aiming for a project structure that looks something like this:

my_project/
|
|____ core/
|    |____ __init__.py
|    |____ views.py           # class based TemplateView for index.html
|    
|
|____ frontend/               # root frontend
|    |____ src/               # vue components, router, store, etc.
|    |____ node_modules/
|    |____ vue.config.js      # important file number 1
|    |____ webpack-stats.json # important file number 2
|
|
|____ my_project/             # root backend
|    |____ __init__.py
|    |____ settings.py
|    |____ urls.py
|    |____ views.py
|
|
|____ templates/                
|    |____ index.html         # django template that houses vue
|
|____ .gitignore
|____ venv/
|____ requirements.txt
|____ manage.py
|____ db.sqlite3

Enter fullscreen mode Exit fullscreen mode

We’ll start with the backend. Create an empty directory for your project, and then run:

$ django-admin startproject my_project && cd my_project
$ mkdir venv && python3 -m venv venv && source venv/bin/activate
$ (venv) pip install django djangorestframework
$ (venv) mkdir templates && cd templates && touch index.html
$ (venv) cd ..
$ (venv) mkdir core && touch __init__.py && touch views.py

Enter fullscreen mode Exit fullscreen mode

This is all we need to do with Django for now. We’ll come back to the templates/index.html and core/views.py files later. This next command assumes you’ve already installed vue globally. If you haven’t, simply run: npm install -g vue-cli

$ vue create frontend

Enter fullscreen mode Exit fullscreen mode

Then walk through the setup wizard so your presets look something like this (or customize your presets as you prefer):

$ Vue CLI v4.3.1
  ? Please pick a preset: Manually select features
  ? Check the features needed for your project: Babel, Router, Vuex
  ? Use history mode for router? (Requires proper server setup for index fallback in production) Yes
  ? Where do you prefer placing config for Babel, ESLint, etc.? In package.json
  ? Save this as a preset for future projects? (y/N) N

  ### installation magic happens...

  Successfully created project frontend.
  Get started with the following commands:
$ cd frontend
$ npm run serve

Enter fullscreen mode Exit fullscreen mode

Now we have separate frontend and backend environments! The frontend server will be at http://localhost:8080/ which will display the Vue landing page, and the backend will be at http://127.0.0.1:8000/ which will display the Django landing page. You can kick off the frontend per above commands and kick off the backend in the root directory with:

python manage.py runserver

Enter fullscreen mode Exit fullscreen mode

Now, these environments just need to be able to talk to each other. The two tools we will use to accomplish this are webpack-bundle-tracker on the Vue side and Django webpack loader on the backend.

$ cd frontend
$ npm install webpack-bundle-tracker@0.4.3

Enter fullscreen mode Exit fullscreen mode

We need version 0.4.3 of webpack-bundle-tracker because the files Django is expecting will not be automatically generated in the same way if we use the latest alpha version. Please note, 0.4.3 is the latest stable release as of April 2020. If we don’t specify this version, npm will pull down the latest alpha version which will not work the same. Next we need to create the vue.config.js file in the frontend directory:

$ touch vue.config.js

Enter fullscreen mode Exit fullscreen mode

and fill it with these contents:

const BundleTracker = require("webpack-bundle-tracker");

module.exports = {
  // on Windows you might want to set publicPath: "http://127.0.0.1:8080/"
  publicPath: "http://0.0.0.0:8080/",
  outputDir: "./dist/",

  chainWebpack: (config) => {
    config
      .plugin("BundleTracker")
      .use(BundleTracker, [{ filename: "./webpack-stats.json" }]);

    config.output.filename("bundle.js");

    config.optimization.splitChunks(false);

    config.resolve.alias.set("__STATIC__", "static");

    config.devServer
      // the first 3 lines of the following code have been added to the configuration
      .public("http://127.0.0.1:8080")
      .host("127.0.0.1")
      .port(8080)
      .hotOnly(true)
      .watchOptions({ poll: 1000 })
      .https(false)
      .disableHostCheck(true)
      .headers({ "Access-Control-Allow-Origin": ["*"] });
  }

  // uncomment before executing 'npm run build'
  // css: {
  // extract: {
  // filename: 'bundle.css',
  // chunkFilename: 'bundle.css',
  // },
  // }
};

Enter fullscreen mode Exit fullscreen mode

Comment out the base url settings that comes with Vue’s router. If you skip this, you’ll just end up having a path like this: http://127.0.0.1:8000/http:/0.0.0.0:8080/blah-blah-blah
to which I say – ew wtf?
Fix it by removing the base url config:

const router = new VueRouter({
  mode: "history",
  // base: process.env.BASE_URL,
  routes
});

Enter fullscreen mode Exit fullscreen mode

Once you create this file, spin up the frontend development server, and a webpack-stats.json file will be generated

npm run serve

Enter fullscreen mode Exit fullscreen mode

Now navigate to the root directory and ensure your virtual environment is activated so we can install django-webpack-loader. Also, feel free to generate your requirements file:

$ (venv) pip install django-webpack-loader
$ pip freeze > requirements.txt

Enter fullscreen mode Exit fullscreen mode

Then, add webpack_loader to Django’s installed apps in settings.py, and add the following changes to the settings.py file:

INSTALLED_APPS = [
         ...
    'rest_framework',
    'webpack_loader',
]

    .
    .
    .
TEMPLATES = [
    {               ...

        'DIRS': [os.path.join(BASE_DIR, 'templates')],
                    ...
    },
]
    .
    .
    .

STATICFILES_DIRS = [
    os.path.join(BASE_DIR, "assets"),
    os.path.join(BASE_DIR, "frontend/dist"),
]

WEBPACK_LOADER = {
    'DEFAULT': {
        'BUNDLE_DIR_NAME': 'dist/',
        'STATS_FILE': os.path.join(BASE_DIR, 'frontend', 'webpack-stats.json')
    }
}

Enter fullscreen mode Exit fullscreen mode

Paste this into your templates/index.html file:

{% 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>Document</title>
  </head>
  <body>
    <!-- This part is in the screenshot at the bottom! -->
    <h1>Vue JS</h1>
    <div id="app"></div>
    {% render_bundle 'app' %}
  </body>
</html>

Enter fullscreen mode Exit fullscreen mode

Paste this into your core/views.py file:

from django.conf import settings
from django.views.generic.base import TemplateView


class IndexTemplateView(TemplateView):
    def get_template_names(self):
        template_name = "index.html"
        return template_name

Enter fullscreen mode Exit fullscreen mode

Make sure these are reflected in your my_project/urls.py file:

from django.urls import re_path
from core.views import IndexTemplateView

urlpatterns = [
    ...
    re_path(r"^.*$", IndexTemplateView.as_view(), name="entry-point"),
]

Enter fullscreen mode Exit fullscreen mode

Once these changes are made, spin up your npm server in one terminal tab, and then spin up your Django dev server in another terminal tab and you should be good to go! Happy coding

$ npm run serve

Enter fullscreen mode Exit fullscreen mode

$ (venv) python manage.py runserver

Enter fullscreen mode Exit fullscreen mode

原文链接:Hooking up Django and Vue.js

© 版权声明
THE END
喜欢就支持一下吧
点赞12 分享
评论 抢沙发

请登录后发表评论

    暂无评论内容