Django和Vue都具有独特的前端优势。Django的上下文驱动模板视图提供了从后端模型内容直接快速开发页面的功能。Vue的现代reactive组件为在丰富的Javascript生态系统中构建复杂的UI提供了强大的工具。
(此处已添加圈子卡片,请到今日头条客户端查看)
然而,将Django和Vue同时使用的典型解决方案削弱了单独使用其中一种的优势。例如,一种常见的方法是使用Django Rest框架作为后端,然后用Vue编写整个前端,这样就很难在方便的地方使用Django模板。第二种方法是在Django模板中使用Vue,通过使用浏览器<script>标记将Vue代码引入,但是这样做就丧失了使用Vue单个文件组件的能力。
最近我启动了一个项目,我想同时使用Django模板和Vue,而不相互影响。我的站点的大多数页面都是相对静态的后端数据列表,交互性有限,这正是Django仅用几行代码就能做到的。但我还有很少的页面包含了更复杂的数据驱动交互区域,而这是Vue的强项。我能不能找到一种方法,在使用Vue丰富页面的部分内容的同时,在更简单的页面上使用Django模板,所有这些都在一个易于管理的配置中呢?
我可以同时拥有两个框架的优势吗?
那是当然!如果不是这样,这篇文章就显得非常无关紧要了。
Django Webpack加载器和Vue多页面应用程序
这个解决方案的关键部分是django -webpack-loader Django应用程序和Vue支持多页面应用程序的能力。通过结合这些工具,我们可以构建一个标准的模板驱动的Django应用程序,该应用程序在Django视图中包含一个或多个独立的webpack包。每个包都是一个单独的Vue“页面”,该页面可以使用所有标准的Vue/Javascript/Webpack工具来构建。
调整Django项目来使用Vue
在本文余下的部分中,我将演示如何修改一个基本的模板驱动的Django应用程序,以使用Vue的单个文件组件。我省略了构建一个简单Django站点的步骤,因为它已经有了很详细的文档,但是如果你想要一个更简单的起点,你可以从example_start标记处访问并使用本文的示例仓库。
出于本文的目的,我假设你有两个工作模板,你希望将单独的Vue组件添加到其中。
在我的示例仓库中,这两个工作模板是templates/vue_app_01.html和templates/vue_app_02.html。
添加一个简单的Vue项目
首先,我们将在Django项目的子目录中嵌入整个简单的Vue项目。首先,确保你安装了Vue CLI。
然后,我们将使用CLI来构建通常要有的 Vue 开始项目,并将其放在vue_frontend目录中
你只需要接受CLI提供的所有缺省值即可。当该项目成功创建时,你会看到CLI的报告信息。我们可以启动它来验证我们的开始项目是否正常工作:
将浏览器指向启动服务命令报告给你的URL(可能是http://localhost:8080),你应该就会看到Vue示例应用程序。
关于如何配置/自定义这个项目的指南或教程,请查看vue-cli文档
将Vue单页应用程序转换为多页应用程序
这个开始项目只有index.js一个入口点。我们将把这个项目转换为使用多个“页面”作为入口点的项目。
首先,我们需要一个助手包webpack-bundle-tracker来帮助我们跟踪由这些多个页面创建的bundle包。你可以从vue_frontend目录运行以下命令,将该助手包添加到项目中。
接下来,我们将重新配置这个Vue项目。创建带有以下内容的vue_fontend / vue.config.js文件:
我们来研究一下这个配置。
在前面,我们声明了一个包含页面vue_app_01和vue_app_02的列表,它们将成为我们bundle包的名称,并且我们还为为每个页面定义入口点。注意main.js附带了我们的开始应用程序,但是我们还没有构建newhampshir.js。我们稍后将构建它。
publicPath部分定义了Django将如何定位我们的bundle包。我们有两种变体可以使用,一种用于生产,另一种用于非生产。在生产中,我们将publicPath设置为空,通过此操作来向django -webpack-loader发出信号,使其退回到Django的标准静态查找器行为。但是,在非生产模式下,我们将覆盖此命令并将其指向我们自己的webpack开发服务器。
outputDir定义了用于生产的Javascript/CSS将放在什么地方。这很可能是你的Django应用程序的一个静态文件位置。
接下来,我们使用splitChunks插件优化我们的构建,对它进行配置使其能够将任何供应商的javascript提取到一个共享bundle中。这样我们就能够保持我们组件的javascript文件很小,并允许浏览器在多个页面之间移动时可以缓存常用的javascript。
默认情况下,Vue会为我们的bundle构造相应的html文件,但是我们不需要这些文件,因为我们可以从Django模板中获取这些文件。通过从配置中删除适当的插件,我们可以阻止这些文件的生成。
BundleTracker插件将创建一个vue_frontend/webpack-stats.json文件, 用来描述此构建过程生成的bundle资源包。此文件最终将被django-webpack-loader用来标识和提供我们的bundle资源包。稍后我会详细介绍。
STATIC别名是Alejandro Riera Mainar首先描述(我认为)的一个巧妙的技巧。它允许我们在Vue组件中按照下边的形式来引用静态文件的路径:
最后,我们来配置一个用于非生产模式的开发服务器,并允许我们在前端开发期间热加载Vue组件。
现在已经配置了Vue,我们需要创建我们的组件。这些组件可以是任何Vue应用程序,但是对于本文,我将只修改starter项目。我们将starter项目的main.js和App. vue转换成另一个稍微不同的应用程序。
接下来,使用vim或你最喜欢的简洁的编辑器去更新src/newhampshir.js,使其指向我们新的App02组件,或者,如果你有sed工具,只需运行以下代码:
同样,对这个App02组件做一个简单的更改,这样我们就能够从浏览器中识别它。再次使用一个编辑器或简单地运行:
现在我们的Vue前端已经准备好了。我们可以通过执行yarn build命令来确认所有东西都已经正确地构建了。你应该会看到一些与下面类似的结果:
对Django进行配置使其使用webpack bundle资源包
现在我们的Vue应用程序正在正确地构建bundle资源包,我们只需要指导Django如何定位和解析这些包。django-webpack-loader项目为我们解决了这方面的大部分问题。在你的requirements.txt中加入以下行,将这个包添加到你的Django应用程序中:
然后安装新的依赖项:
在你的Django设置文件中(例如settings.py),将webpack_loader添加到INSTALLED_APPS列表中。
在相同设置文件的其他地方,添加以下行:
这个配置会将django-webpack-loader指向我们在Vue构建期间生成的stats文件。
到这里差不多就完成了。最后一步是修改模板,将我们新的Vue应用程序包括进来。选择一个你现有的Django模板文件(在我的例子中是vue_app_01.html),并添加以下内容:
这段代码为我们的应用程序预留了一个容器,然后将来自供应商的bundle包和我们的vue_app_01 bundle包所需要的所有Javascript和CSS包含进来。注意,你可以将任何现有的Django模板代码混合到这些新增代码中。
选择第二个模板并包含相同的内容,除了替换vue_app_02 bundle包。
运行这个应用程序
要在开发模式下运行我们的应用程序,我们需要同时提供Django的开发服务器和webpack开发服务器。从vue_frontend目录中运行:
并且,在Django根目录中的另一个终端中运行Django开发服务器,例如。
将浏览器指向你的Django应用程序(例如http://localhost:8000),查看你修改的两个页面。你应该能看到你的模板,但是现在每个模板都运行着一个单独的Vue组件。
检查浏览器的开发控制台,你可以看到Vue JS/CSS是由我们的webpack开发服务器提供的。再有,这两个组件共享着相同的chunk-vendor .js bundle包。此外,我们可以通过更改我们的组件之一来演示热重载是正确运行的。不需要重新加载,更新就会直接在浏览器中生效。
是时候进行部署的时候,或者当我们只是想要省略运行Vue 开发服务器时,我们就可以在生产模式中构建我们的Vue项目。如果 yarn serve进程正在运行,就取消它,并运行yarn build。优化后的bundle包将内置于我们的Django静态文件位置,并且 webpack-stats.json将会被更新来生效这个新配置。回到你的web浏览器,重新加载页面,你会看到Vue JS/CSS bundle包现在已经从标准静态文件位置来加载了。
结论
结合Django模板和Vue并不要求你在这两种模板的优点上做出妥协。使用本文描述的技术,你可以在项目中任何适当的时间和地点自由地利用它们。
补充说明
本例中使用的Vue组件非常简单,但是你可以随心所欲地将它们变得复杂,通过Vuex和Vuetify等技术、第三方node模块或其他webpack配置。只需修改你的Vue/Webpack配置,就像使用任何标准的Vue项目一样。
使用这项技术,你就不受限于每页只有一个Vue组件。如果你希望将多个组件挂载在单个页面上的单独容器中,只需使用一个单独的选择器来相应地挂载每个组件。
我不提倡任何特定的生产配置方法。你可能希望提交一个生产webpack-stats.json,为开发/生产环境维护两个单独的版本,或者将bundle包的构建和webpack-stats.json包含到你的交付进程中。
致谢
Rodrigo Smaniotto的那篇极好的文章——“使用Vue CLI 3和Webpack Loader将Django和VueJs集成在一起”——教会了我如何使用django-webpack-loader去集成一个Vue单页面应用程序。本文描述的大部分django-webpack-loader配置都是基于他的研究工作。
Rodrigo的文章和本文还使用了Alejandro Riera Mainar的“使用Django + webpack + Vue建立一个易于开发和部署的新项目(第1部分)”这篇文章中的内容。
注:我这有个学习Python基地,里面有很多学习资料,感兴趣的+Q群:895817687