diff --git a/LICENSE b/LICENSE index a67e4da21..efbb72870 100644 --- a/LICENSE +++ b/LICENSE @@ -1,4 +1,4 @@ -Copyright (c) 2013-2020, Daniel Roy Greenfeld +Copyright (c) 2013-2020, Daniel Roy Greenfeld, Mike Hoolehan All rights reserved. Redistribution and use in source and binary forms, with or without modification, diff --git a/README.rst b/README.rst index 47f2bfb7d..45d2b7dff 100644 --- a/README.rst +++ b/README.rst @@ -1,323 +1,100 @@ -Cookiecutter Django +Cookiecutter Vue Django ======================= -.. image:: https://travis-ci.org/pydanny/cookiecutter-django.svg?branch=master - :target: https://travis-ci.org/pydanny/cookiecutter-django?branch=master +.. image:: https://travis-ci.com/ilikerobots/cookiecutter-vue-django.svg?branch=master + :target: https://travis-ci.com/ilikerobots/cookiecutter-vue-django?branch=master :alt: Build Status -.. image:: https://readthedocs.org/projects/cookiecutter-django/badge/?version=latest - :target: https://cookiecutter-django.readthedocs.io/en/latest/?badge=latest +.. image:: https://readthedocs.org/projects/cookiecutter-vue-django/badge/?version=latest + :target: https://cookiecutter-vue-django.readthedocs.io/en/latest/?badge=latest :alt: Documentation Status -.. image:: https://pyup.io/repos/github/pydanny/cookiecutter-django/shield.svg - :target: https://pyup.io/repos/github/pydanny/cookiecutter-django/ +.. image:: https://pyup.io/repos/github/ilikerobots/cookiecutter-vue-django/shield.svg + :target: https://pyup.io/repos/github/ilikerobots/cookiecutter-vue-django/ :alt: Updates -.. image:: https://img.shields.io/badge/cookiecutter-Join%20on%20Slack-green?style=flat&logo=slack - :target: https://join.slack.com/t/cookie-cutter/shared_invite/enQtNzI0Mzg5NjE5Nzk5LTRlYWI2YTZhYmQ4YmU1Y2Q2NmE1ZjkwOGM0NDQyNTIwY2M4ZTgyNDVkNjMxMDdhZGI5ZGE5YmJjM2M3ODJlY2U +Vue + Django with no compromise. -.. image:: https://www.codetriage.com/pydanny/cookiecutter-django/badges/users.svg - :target: https://www.codetriage.com/pydanny/cookiecutter-django - :alt: Code Helpers Badge +Cookiecutter Vue Django is a framework for jumpstarting production-ready Django + Vue projects quickly. Expanding on the the wonderful Cookiecutter Django, this project template allows the intermingling of both Django Templates and Vue, even on the same page, without compromising the full power of either. -.. image:: https://img.shields.io/badge/code%20style-black-000000.svg - :target: https://github.com/ambv/black - :alt: Code style: black +Typical solutions to integrating Django and Vue forgo much of the strengths of one lieu of the other. For example, a common approach is using Django Rest Framework as backend and writing the entire front end in Vue, making it difficult to utilize Django templates in places it could be expedient. A second approach is to use Vue within Django templates using browser ` + +{% endblock %}{% endraw %} diff --git a/{{cookiecutter.project_slug}}/fruit/tests.py b/{{cookiecutter.project_slug}}/fruit/tests.py new file mode 100644 index 000000000..a39b155ac --- /dev/null +++ b/{{cookiecutter.project_slug}}/fruit/tests.py @@ -0,0 +1 @@ +# Create your tests here. diff --git a/{{cookiecutter.project_slug}}/fruit/urls.py b/{{cookiecutter.project_slug}}/fruit/urls.py new file mode 100644 index 000000000..b786a24ad --- /dev/null +++ b/{{cookiecutter.project_slug}}/fruit/urls.py @@ -0,0 +1,25 @@ +from django.urls import path +from django.views.generic import TemplateView +{%- if cookiecutter.use_drf == "y" %} +from fruit.views import FruitList +{%- endif %} + +app_name = "fruit" + +urlpatterns = [ + {%- if cookiecutter.use_drf == "y" %} + path( + "fruits/", + FruitList.as_view(extra_context={"title": "Fruit Inspector"}), + name="list", + ), + {% endif -%} + path( + "fruit-counter/", + TemplateView.as_view( + template_name="fruit/counter.html", + extra_context={"counter_message": "How many fruits could you eat?"}, + ), + name="counter", + ), +] diff --git a/{{cookiecutter.project_slug}}/fruit/views.py b/{{cookiecutter.project_slug}}/fruit/views.py new file mode 100644 index 000000000..6a38b3ec8 --- /dev/null +++ b/{{cookiecutter.project_slug}}/fruit/views.py @@ -0,0 +1,6 @@ +from django.views.generic import ListView +from fruit.models import Fruit + + +class FruitList(ListView): + model = Fruit diff --git a/{{cookiecutter.project_slug}}/requirements/base.txt b/{{cookiecutter.project_slug}}/requirements/base.txt index ba62bae08..9daeea66f 100644 --- a/{{cookiecutter.project_slug}}/requirements/base.txt +++ b/{{cookiecutter.project_slug}}/requirements/base.txt @@ -42,3 +42,6 @@ django-redis==4.12.1 # https://github.com/jazzband/django-redis # Django REST Framework djangorestframework==3.11.0 # https://github.com/encode/django-rest-framework {%- endif %} +{%- if cookiecutter.use_vue == "y" %} +django-webpack-loader==0.6.0 # https://github.com/owais/django-webpack-loader +{%- endif %} diff --git a/{{cookiecutter.project_slug}}/vue_frontend/.browserslistrc b/{{cookiecutter.project_slug}}/vue_frontend/.browserslistrc new file mode 100644 index 000000000..214388fe4 --- /dev/null +++ b/{{cookiecutter.project_slug}}/vue_frontend/.browserslistrc @@ -0,0 +1,3 @@ +> 1% +last 2 versions +not dead diff --git a/{{cookiecutter.project_slug}}/vue_frontend/.env b/{{cookiecutter.project_slug}}/vue_frontend/.env new file mode 100644 index 000000000..8b0726f30 --- /dev/null +++ b/{{cookiecutter.project_slug}}/vue_frontend/.env @@ -0,0 +1,3 @@ +VUE_APP_STATIC_ROOT=http://localhost:8000/static +VUE_APP_API_ROOT=http://localhost:8000/api + diff --git a/{{cookiecutter.project_slug}}/vue_frontend/.eslintrc.js b/{{cookiecutter.project_slug}}/vue_frontend/.eslintrc.js new file mode 100644 index 000000000..8ad90db46 --- /dev/null +++ b/{{cookiecutter.project_slug}}/vue_frontend/.eslintrc.js @@ -0,0 +1,17 @@ +module.exports = { + root: true, + env: { + node: true + }, + 'extends': [ + 'plugin:vue/essential', + 'eslint:recommended' + ], + parserOptions: { + parser: 'babel-eslint' + }, + rules: { + 'no-console': process.env.NODE_ENV === 'production' ? 'warn' : 'off', + 'no-debugger': process.env.NODE_ENV === 'production' ? 'warn' : 'off' + } +} diff --git a/{{cookiecutter.project_slug}}/vue_frontend/.gitignore b/{{cookiecutter.project_slug}}/vue_frontend/.gitignore new file mode 100644 index 000000000..fc546a5b9 --- /dev/null +++ b/{{cookiecutter.project_slug}}/vue_frontend/.gitignore @@ -0,0 +1,23 @@ +.DS_Store +node_modules +/dist + +# local env files +.env.local +.env.*.local +!.env + +# Log files +npm-debug.log* +yarn-debug.log* +yarn-error.log* +pnpm-debug.log* + +# Editor directories and files +.idea +.vscode +*.suo +*.ntvs* +*.njsproj +*.sln +*.sw? diff --git a/{{cookiecutter.project_slug}}/vue_frontend/README.md b/{{cookiecutter.project_slug}}/vue_frontend/README.md new file mode 100644 index 000000000..fd2a3556a --- /dev/null +++ b/{{cookiecutter.project_slug}}/vue_frontend/README.md @@ -0,0 +1,24 @@ +# vue_frontend + +## Project setup +`yarn install` or `npm install` + +### Compiles and hot-reloads for development +`yarn serve` or `npm run serve` + +{% if cookiecutter.use_pycharm == 'y' -%} +Or use the PyCharm run configuration *Vue serve*. +{%- endif %} + +### Compiles and minifies for production +`yarn build` or `npm run build` + +{% if cookiecutter.use_pycharm == 'y' -%} +Or use the PyCharm run configuration *Vue build*. +{%- endif %} + +### Lints and fixes files +`yarn lint` or `npm run lint` + +### Customize configuration +See [Configuration Reference](https://cli.vuejs.org/config/). diff --git a/{{cookiecutter.project_slug}}/vue_frontend/babel.config.js b/{{cookiecutter.project_slug}}/vue_frontend/babel.config.js new file mode 100644 index 000000000..e9558405f --- /dev/null +++ b/{{cookiecutter.project_slug}}/vue_frontend/babel.config.js @@ -0,0 +1,5 @@ +module.exports = { + presets: [ + '@vue/cli-plugin-babel/preset' + ] +} diff --git a/{{cookiecutter.project_slug}}/vue_frontend/package.json b/{{cookiecutter.project_slug}}/vue_frontend/package.json new file mode 100644 index 000000000..2622edb3c --- /dev/null +++ b/{{cookiecutter.project_slug}}/vue_frontend/package.json @@ -0,0 +1,31 @@ +{ + "name": "vue_frontend", + "version": "0.1.0", + "private": true, + "scripts": { + "serve": "vue-cli-service serve", + "build": "vue-cli-service build", + "lint": "vue-cli-service lint" + }, + "dependencies": { + "axios": "^0.19.2", + "core-js": "^3.6.5", + "vue": "^2.6.11"{% if cookiecutter.use_vuex == 'y' -%}, + "vuex": "^3.4.0", + "vuex-persistedstate": "^3.0.1" + {%- endif %} +}, + "devDependencies": { + "@vue/cli-plugin-babel": "~4.4.0", + "@vue/cli-plugin-eslint": "~4.4.0", + "@vue/cli-plugin-vuex": "~4.4.0", + "@vue/cli-service": "~4.4.0", + "babel-eslint": "^10.1.0", + "eslint": "^6.7.2", + "eslint-plugin-vue": "^6.2.2", + "node-sass": "^4.12.0", + "sass-loader": "^8.0.2", + "vue-template-compiler": "^2.6.11", + "webpack-bundle-tracker": "^0.4.3" + } +} diff --git a/{{cookiecutter.project_slug}}/vue_frontend/src/fruit/components/Counter.vue b/{{cookiecutter.project_slug}}/vue_frontend/src/fruit/components/Counter.vue new file mode 100644 index 000000000..56df8292f --- /dev/null +++ b/{{cookiecutter.project_slug}}/vue_frontend/src/fruit/components/Counter.vue @@ -0,0 +1,56 @@ + + + + + + diff --git a/{{cookiecutter.project_slug}}/vue_frontend/src/fruit/components/CounterAdjustor.vue b/{{cookiecutter.project_slug}}/vue_frontend/src/fruit/components/CounterAdjustor.vue new file mode 100644 index 000000000..09ae9d2a7 --- /dev/null +++ b/{{cookiecutter.project_slug}}/vue_frontend/src/fruit/components/CounterAdjustor.vue @@ -0,0 +1,55 @@ + + + + + diff --git a/{{cookiecutter.project_slug}}/vue_frontend/src/fruit/components/CounterBanner.vue b/{{cookiecutter.project_slug}}/vue_frontend/src/fruit/components/CounterBanner.vue new file mode 100644 index 000000000..3ff84010c --- /dev/null +++ b/{{cookiecutter.project_slug}}/vue_frontend/src/fruit/components/CounterBanner.vue @@ -0,0 +1,34 @@ + + + + + + \ No newline at end of file diff --git a/{{cookiecutter.project_slug}}/vue_frontend/src/fruit/components/CounterDisplay.vue b/{{cookiecutter.project_slug}}/vue_frontend/src/fruit/components/CounterDisplay.vue new file mode 100644 index 000000000..d368e1415 --- /dev/null +++ b/{{cookiecutter.project_slug}}/vue_frontend/src/fruit/components/CounterDisplay.vue @@ -0,0 +1,43 @@ + + + + + + diff --git a/{{cookiecutter.project_slug}}/vue_frontend/src/fruit/components/FruitInspector.vue b/{{cookiecutter.project_slug}}/vue_frontend/src/fruit/components/FruitInspector.vue new file mode 100644 index 000000000..be14b05f5 --- /dev/null +++ b/{{cookiecutter.project_slug}}/vue_frontend/src/fruit/components/FruitInspector.vue @@ -0,0 +1,106 @@ + + + + + diff --git a/{{cookiecutter.project_slug}}/vue_frontend/src/fruit/entry/fruit_counter.js b/{{cookiecutter.project_slug}}/vue_frontend/src/fruit/entry/fruit_counter.js new file mode 100644 index 000000000..c9301a7ae --- /dev/null +++ b/{{cookiecutter.project_slug}}/vue_frontend/src/fruit/entry/fruit_counter.js @@ -0,0 +1,34 @@ +import Vue from "vue/dist/vue.js"; +import storePlugin from "../../../../vue_frontend/src/store/vuex_store_as_plugin"; +import createPersistedState from "vuex-persistedstate"; +import FruitModule from "../store/module_fruit" +const Counter = () => import( /* webpackChunkName: "chunk-counter" */ "../components/Counter.vue"); +const CounterBanner = () => import( /* webpackChunkName: "chunk-counter-banner" */ "../components/CounterBanner.vue"); + +Vue.config.productionTip = false + +// Vuex state will be used in this entry point +Vue.use(storePlugin); + +// Include Vuex modules as needed for this entry point +Vue.prototype.$store.registerModule('fruit', FruitModule); + +// Designate what state should persist across page loads +createPersistedState({ + paths: [ + "fruit.count", + "fruit.activeFruit", + ] + } +)(Vue.prototype.$store); + +// Mount top level components +new Vue({ + el: "#app", + components: {Counter} +}); + +new Vue({ + el: "#counter_banner", + components: {CounterBanner} +}); diff --git a/{{cookiecutter.project_slug}}/vue_frontend/src/fruit/entry/fruit_list.js b/{{cookiecutter.project_slug}}/vue_frontend/src/fruit/entry/fruit_list.js new file mode 100644 index 000000000..0d286e9b0 --- /dev/null +++ b/{{cookiecutter.project_slug}}/vue_frontend/src/fruit/entry/fruit_list.js @@ -0,0 +1,30 @@ +import Vue from "vue/dist/vue.js"; +import storePlugin from "../../store/vuex_store_as_plugin"; +import createPersistedState from "vuex-persistedstate"; +import FruitModule from "../store/module_fruit" +const FruitInspector = () => import( /* webpackChunkName: "chunk-fruit-inspector" */ "../components/FruitInspector.vue"); + +Vue.config.productionTip = false + +// Vuex state will be used in this entry point +Vue.use(storePlugin); + +// Include Vuex modules as needed for this entry point +Vue.prototype.$store.registerModule('fruit', FruitModule); + + +// Designate what state should persist across page loads +createPersistedState({ + paths: [ + "fruit.count", + "fruit.activeFruit", + ] + } +)(Vue.prototype.$store); + +// Mount top level components +new Vue({ + el: "#app", + components: {FruitInspector} +}); + diff --git a/{{cookiecutter.project_slug}}/vue_frontend/src/fruit/store/module_fruit.js b/{{cookiecutter.project_slug}}/vue_frontend/src/fruit/store/module_fruit.js new file mode 100644 index 000000000..1728f03b5 --- /dev/null +++ b/{{cookiecutter.project_slug}}/vue_frontend/src/fruit/store/module_fruit.js @@ -0,0 +1,77 @@ +{%- if cookiecutter.use_drf == 'y' -%} +import api from "../../rest/rest"; + +{%- endif -%} +export const MAX_COUNT = 42 +export const MIN_COUNT = 0 + +{%- if cookiecutter.use_drf == 'y' %} +export const ACTION_GET_FRUITS = 'ACT_GET_FRUITS' +export const ACTION_SET_ACTIVE_FRUIT = 'ACT_SET_ACTIVE_FRUIT' +{%- endif %} +export const ACTION_INCREMENT_COUNTER = 'ACT_INC_COUNT' +export const ACTION_DECREMENT_COUNTER = 'ACT_DEC_COUNT' + +{%- if cookiecutter.use_drf == 'y' %} +const MUTATION_SET_FRUITS = 'MUT_SET_FRUITS' +const MUTATION_SET_ACTIVE_FRUIT = 'MUT_SET_ACTIVE_FRUIT' +{%- endif %} +const MUTATION_INCREMENT_COUNTER = 'MUT_INC_COUNT' +const MUTATION_DECREMENT_COUNTER = 'MUT_DEC_COUNT' + +export default { + state: { + count: 0, + {%- if cookiecutter.use_drf == 'y' %} + fruits: [], + activeFruit: null, + {%- endif %} + }, + mutations: { + {%- if cookiecutter.use_drf == 'y' %} + [MUTATION_SET_FRUITS](state, fruitList) { + state.fruits = fruitList; + }, + [MUTATION_SET_ACTIVE_FRUIT](state, fruit) { + state.activeFruit = fruit; + }, + {%- endif %} + [MUTATION_INCREMENT_COUNTER]: state => state.count++, + [MUTATION_DECREMENT_COUNTER]: state => state.count-- + }, + actions: { + {%- if cookiecutter.use_drf == 'y' %} + [ACTION_GET_FRUITS](context) { + api.getFruits() + .then(function (response) { + context.commit(MUTATION_SET_FRUITS, response.data); + }) + .catch(function (error) { + // handle error + console.log(error); + }); + }, + [ACTION_SET_ACTIVE_FRUIT](context, fruitId) { + api.getFruit(fruitId) + .then(function (response) { + context.commit(MUTATION_SET_ACTIVE_FRUIT, response.data); + }) + .catch(function (error) { + // handle error + console.log(error); + }); + }, + {%- endif %} + [ACTION_INCREMENT_COUNTER](context) { + if (context.state.count < MAX_COUNT) { + context.commit(MUTATION_INCREMENT_COUNTER); + } + }, + [ACTION_DECREMENT_COUNTER](context) { + if (context.state.count > MIN_COUNT) { + context.commit(MUTATION_DECREMENT_COUNTER); + } + } + + }, +} \ No newline at end of file diff --git a/{{cookiecutter.project_slug}}/vue_frontend/src/rest/rest.js b/{{cookiecutter.project_slug}}/vue_frontend/src/rest/rest.js new file mode 100644 index 000000000..9ebe64912 --- /dev/null +++ b/{{cookiecutter.project_slug}}/vue_frontend/src/rest/rest.js @@ -0,0 +1,23 @@ +import axios from "axios"; + +// axios settings +axios.defaults.baseURL = process.env.VUE_APP_API_ROOT; +axios.defaults.xsrfHeaderName = "X-CSRFToken"; +axios.defaults.xsrfCookieName = 'csrftoken'; + + +const api = axios.create({}); + + +export default { +{%- if cookiecutter.use_fruit_demo == "y" %} + getFruits: function () { + return api.get('/fruits/') + }, + getFruit: function (id) { + return api.get('/fruits/' + id + '/') + } +{%- endif %} + /* Include additional API calls here */ +} + diff --git a/{{cookiecutter.project_slug}}/vue_frontend/src/store/vuex_store_as_plugin.js b/{{cookiecutter.project_slug}}/vue_frontend/src/store/vuex_store_as_plugin.js new file mode 100644 index 000000000..c51c5ac95 --- /dev/null +++ b/{{cookiecutter.project_slug}}/vue_frontend/src/store/vuex_store_as_plugin.js @@ -0,0 +1,17 @@ +import Vue from "vue/dist/vue.js"; +import Vuex from "vuex"; + +Vue.use(Vuex); + +let store = new Vuex.Store({ + modules: { + }, + strict: process.env.NODE_ENV !== "production", +}); + +export default { + store, + install(Vue) { //resetting the default store to use this plugin store + Vue.prototype.$store = store; + } +} \ No newline at end of file diff --git a/{{cookiecutter.project_slug}}/vue_frontend/src/{{cookiecutter.project_slug}}/assets/logo.png b/{{cookiecutter.project_slug}}/vue_frontend/src/{{cookiecutter.project_slug}}/assets/logo.png new file mode 100644 index 000000000..f3d2503fc Binary files /dev/null and b/{{cookiecutter.project_slug}}/vue_frontend/src/{{cookiecutter.project_slug}}/assets/logo.png differ diff --git a/{{cookiecutter.project_slug}}/vue_frontend/src/{{cookiecutter.project_slug}}/components/HelloWorld.vue b/{{cookiecutter.project_slug}}/vue_frontend/src/{{cookiecutter.project_slug}}/components/HelloWorld.vue new file mode 100644 index 000000000..b17d4ad26 --- /dev/null +++ b/{{cookiecutter.project_slug}}/vue_frontend/src/{{cookiecutter.project_slug}}/components/HelloWorld.vue @@ -0,0 +1,116 @@ + + + + + + diff --git a/{{cookiecutter.project_slug}}/vue_frontend/src/{{cookiecutter.project_slug}}/entry/main.js b/{{cookiecutter.project_slug}}/vue_frontend/src/{{cookiecutter.project_slug}}/entry/main.js new file mode 100644 index 000000000..6ba1a968e --- /dev/null +++ b/{{cookiecutter.project_slug}}/vue_frontend/src/{{cookiecutter.project_slug}}/entry/main.js @@ -0,0 +1,10 @@ +import Vue from "vue/dist/vue.js"; +const HelloWorld = () => import( /* webpackChunkName: "chunk-hello-world" */ "../components/HelloWorld.vue"); + +Vue.config.productionTip = false + +// Mount top level components +new Vue({ + el: "#app", + components: {HelloWorld} +}); diff --git a/{{cookiecutter.project_slug}}/vue_frontend/vue.config.js b/{{cookiecutter.project_slug}}/vue_frontend/vue.config.js new file mode 100644 index 000000000..c90b0b941 --- /dev/null +++ b/{{cookiecutter.project_slug}}/vue_frontend/vue.config.js @@ -0,0 +1,88 @@ +const BundleTracker = require("webpack-bundle-tracker"); +const BundleAnalyzerPlugin = require("webpack-bundle-analyzer").BundleAnalyzerPlugin; + + +const pages = { + 'main': { + entry: './src/{{cookiecutter.project_slug}}/entry/main.js', + chunks: ['chunk-common'] + }, + {%- if cookiecutter.use_fruit_demo == 'y' %} + 'fruit-counter': { + entry: './src/fruit/entry/fruit_counter.js', + chunks: ['chunk-common', 'chunk-state'] + }, + {%- endif %}{%- if cookiecutter.use_fruit_demo == 'y' and cookiecutter.use_drf == 'y' %} + 'fruit-list': { + entry: './src/fruit/entry/fruit_list.js', + chunks: ['chunk-common', 'chunk-state'] + }, + {%- endif %} +} + +module.exports = { + pages: pages, + filenameHashing: true, + productionSourceMap: false, + publicPath: process.env.NODE_ENV === 'production' + ? '/static/vue' + : 'http://localhost:8080/', + outputDir: '../{{cookiecutter.project_slug}}/static/vue/', + + chainWebpack: config => { + + config.optimization + .splitChunks({ + cacheGroups: { + state: { + /* As vuex state is not needed in all our entry points, we isolate it + * in a separate chunk to be loaded only where needed. + */ + test: /[\\/]node_modules[\\/](vuex|vuex-persisted-state)/, + name: "chunk-state", + chunks: "all", + priority: 5 + }, + vendor: { + /* This chunk contains modules that may be used in all entry points, + * including Vue itself + */ + test: /[\\/]node_modules[\\/]/, + name: "chunk-common", + chunks: "all", + priority: 1 + }, + }, + }); + + Object.keys(pages).forEach(page => { + config.plugins.delete(`html-${page}`); + config.plugins.delete(`preload-${page}`); + config.plugins.delete(`prefetch-${page}`); + }) + + config + .plugin('BundleTracker') + .use(BundleTracker, [{ + path: '../vue_frontend/', + filename: 'webpack-stats.json' + }]); + + // Uncomment below to analyze bundle sizes + // config.plugin("BundleAnalyzerPlugin").use(BundleAnalyzerPlugin); + + // config.resolve.alias + // .set('__STATIC__', 'static') + + config.devServer + .public('http://localhost:8080') + .host('localhost') + .port(8080) + .hotOnly(true) + .watchOptions({poll: 1000}) + .https(false) + .headers({"Access-Control-Allow-Origin": ["*"]}) + + } +}; + diff --git a/{{cookiecutter.project_slug}}/{{cookiecutter.project_slug}}/static/images/django_logo.png b/{{cookiecutter.project_slug}}/{{cookiecutter.project_slug}}/static/images/django_logo.png new file mode 100644 index 000000000..68706a474 Binary files /dev/null and b/{{cookiecutter.project_slug}}/{{cookiecutter.project_slug}}/static/images/django_logo.png differ diff --git a/{{cookiecutter.project_slug}}/{{cookiecutter.project_slug}}/static/js/project.js b/{{cookiecutter.project_slug}}/{{cookiecutter.project_slug}}/static/js/project.js index d26d23b9b..d5094b2eb 100644 --- a/{{cookiecutter.project_slug}}/{{cookiecutter.project_slug}}/static/js/project.js +++ b/{{cookiecutter.project_slug}}/{{cookiecutter.project_slug}}/static/js/project.js @@ -1 +1,19 @@ +{%- if cookiecutter.use_vue == 'y' %} +function load_bundle_file(url, filetype) { + let fileref; + if (filetype === "js") { // build js script tag + fileref = document.createElement('script'); + fileref.setAttribute("type", "text/javascript"); + fileref.setAttribute("src", url); + } else if (filetype === "css") { // build css link tag + fileref = document.createElement("link"); + fileref.setAttribute("rel", "stylesheet"); + fileref.setAttribute("type", "text/css"); + fileref.setAttribute("href", url); + } + if (typeof fileref != "undefined") + document.getElementsByTagName("head")[0].appendChild(fileref); +} + +{% endif -%} /* Project specific Javascript goes here. */ diff --git a/{{cookiecutter.project_slug}}/{{cookiecutter.project_slug}}/static/sass/custom_bootstrap_vars.scss b/{{cookiecutter.project_slug}}/{{cookiecutter.project_slug}}/static/sass/custom_bootstrap_vars.scss index e69de29bb..bb61cf415 100644 --- a/{{cookiecutter.project_slug}}/{{cookiecutter.project_slug}}/static/sass/custom_bootstrap_vars.scss +++ b/{{cookiecutter.project_slug}}/{{cookiecutter.project_slug}}/static/sass/custom_bootstrap_vars.scss @@ -0,0 +1,4 @@ +{%- if cookiecutter.use_vue == 'y' -%} +$vue-blue: #34495E; +$vue-green: #41B883; +{% endif -%} diff --git a/{{cookiecutter.project_slug}}/{{cookiecutter.project_slug}}/templates/base.html b/{{cookiecutter.project_slug}}/{{cookiecutter.project_slug}}/templates/base.html index cba1b7cf7..39530042f 100644 --- a/{{cookiecutter.project_slug}}/{{cookiecutter.project_slug}}/templates/base.html +++ b/{{cookiecutter.project_slug}}/{{cookiecutter.project_slug}}/templates/base.html @@ -50,7 +50,13 @@ + {% endraw %}{% if cookiecutter.use_fruit_demo == "y" %}{% raw %} + {% endraw %}{% endif %}{% if cookiecutter.use_fruit_demo == "y" and cookiecutter.use_drf == "y"%}{% raw %} + {% endraw %}{% endif %}{% raw %} {% if request.user.is_authenticated %}