在django中整合vue2单页面应用

0
(0)

django中最常用的是使用内置的模板和admin,但是现在很流行前后端分离的开发方式,后端程序只提供RESTFUL接口,前端程序绘制页面交互, 相比之下,基于模板的开发方式就显得不那么灵活,而且有一定的学习成本。

如果在django模板直接引用vue.js的方式进行开发,还要考虑到模板标签的冲突问题,要么更换vue模板标签,要么使用特定标签verbatim进行处理,保证django模板能够正确的区分django 的标签和vue的标签,但是开发人员仍然要注意两种模板的语法区别。

...
<div id="app">
{{ django_var }}

{% verbatim vueblock %}
...
<div class="title">{{ vue_var }}</div>
...
<script src=".../vue.js"></script>
<script>
    new Vue({
        el: '#app',
        data: {
            vue_var: 'this is a test',
        },
        ...
    })
</script>
{% endverbatim vueblock%}
</div>

如果采用前后端分离的开发方式,最彻底的方式就是抛弃掉django admin,完全重写后端接口和前端页面,那么工作量会增加很多,还要单独熟悉 django auth的业务逻辑和表结构。 既然不用django admin了,那也可以不用django了, 不如换成 FastAPI,flask写后端接口吧…

话说回来,正好有一个使用django开发的预约管理系统,包含了字典,设置,会员,排班预约等很多功能页面。其中预约页面是以列表形式展现的,不够直观,业务部门期望能够以日历的形式更直观的展示

经过评估,django开发认为,可以自定义changelist.html模板,但在页面中使用vue工作量比较大。vue不太熟悉django模板,需要学习。最终方案,创建一个vue单页面项目, 后端使用django提供页面的接口,在django admin的菜单中挂前端页面的链接。

这里说一下,实现的方式,在预约项目的根目录创建一个前端页面目录web,dist目录是我的前端构建产物。router/index.js是 vue的路由代码

在django的settings.py中,修改模板配置,使其包含 web/dist目录

TEMPLATES = [
    {
        'BACKEND': 'django.template.backends.django.DjangoTemplates',
        'DIRS': ['templates', os.path.join(BASE_DIR, 'web/dist')],
        'APP_DIRS': True,
        ...
    }
]

配置好模板后,还要管理静态资源文件,在settings.py中还要配置静态资源目录,使其包含 web/dist

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

在django的主urls.py中,增加一行配置,为了让django能够托管vue的页面

urlpatterns = [
    ...
    path('web/', TemplateView.as_view(template_name='index.html')),
]

以上配置完成后, 使用 npm run build之类的命令对前端项目打包后,就会生成dist目录, 再启动django程序,就能用整合好的地址访问页面了: http://127.0.0.1:8000/web/#/

下一步, 把django admin的菜单地址替换掉,还要考虑潜在的传参数的问题,那就加一个模板处理,在templates目录下创建一个模板文件 appointlist/redirect.html,内容如下:

<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
</head>
<body>
<script>
    window.location.href = '/web/#/?userid={{userid}}&param2={{param2}}'
</script>
</body>
</html>

然后,在admin.py中的管理类中,修改 change_list_template属性,指向刚定义的模板

@admin.register(ReservationList)
class ReservationGridAdmin(ModelAdmin):
    change_list_template = 'book_reservation/reserve.html'

    def changelist_view(self, request, extra_context=None):
        userid = request.user.id
        param2 = 'this is a spreadsheet'
        extra_context = {'userid': userid, 'param2': param2}
        return super().changelist_view(request, extra_context)

再重新运行django程序看效果

总结一下,不改变整体django程序的情况下,个别页面使用vue单页面方式进行开发是可行的,完美的融入到django的菜单体系中,需要在django中做一些相应的配置,单独实现页面所需的接口, 前端开发不需要更多的时间学习新的模板语法,更不需要考虑在django模板中使用其他语法带来的工作量提升。

2025/9/14 于 北京 上东廓

这篇文章有用吗?

点击星号为它评分!

平均评分 0 / 5. 投票数: 0

到目前为止还没有投票!成为第一位评论此文章。

很抱歉,这篇文章对您没有用!

让我们改善这篇文章!

告诉我们我们如何改善这篇文章?

发表回复

您的邮箱地址不会被公开。 必填项已用 * 标注