【无标题】从0到1 搭建一个vue3+Django项目

目录

      • 一、后端项目python django
      • 二、前端项目vite+vue3
      • 三、后端配置
        • 3.1 将路由指向app
        • 3.2 app下创建urls.py, 写入路由
        • 3.3 views写入test函数
        • 3.4 启动服务,访问路由
      • 四、前端配置
        • 4.1 安装一些工具库及创建文件
            • 4.1.1 安装需要用的三方库
            • 4.1.2 创建文件
        • 4.2 配置、写代码
            • 4.2.1 vite.config.js [参考](https://juejin.cn/post/7282691800858869797)
            • 4.2.2 src/main.js
            • 4.2.3 请求封装 [参考](https://juejin.cn/post/7036341194716086279)
            • 4.2.4 页面菜单
            • 4.2.5 页面
            • 4.2.6 路由 [参考](https://blog.csdn.net/xjtarzan/article/details/119736309)
            • 4.2.7 logo
            • 4.2.8 App.vue
        • 4.3 启动前端项目、测试接口联通性
      • 五、问题
        • 5.1 跨域![在这里插入图片描述](https://img-blog.csdnimg.cn/direct/1b9e520a4af1479e9f5a20bb523e1567.png)
            • 方法1:vite.config.js配置前端代理
            • 方法2:后端解除限制
        • 5.2 不允许访问
            • 方法1:在前端代理
            • 方法2:在后端加入白名单
      • 六、vue项目部署到Django
        • 6.1 前端打包
        • 6.2 将打包好的文件夹放到django项目中
            • 6.2.1 新建一个templates文件夹,放入前端打包文件
        • 6.3 修改ocrExcel/urls.py
        • 6.4 修改setting.py
            • 6.4.1 找到TEMPLATES,在DIRS中加入`os.path.join(BASE_DIR, 'templates/dist')`
            • 6.4.2 找到STATIC_URL,修改
        • 6.5 启动Django
      • 结语

基础环境版本:
python: 3.9.9
pip: 23.3.1
django: 4.2.7
node: 18.14.0
npm: 9.3.1
vue: 3.3.8
vite: 5.0.0
工具: vs code

一、后端项目python django

django 创建项目跟着官网步骤

  1. 创建项目:django-admin startproject corExcel
  2. 进入文件夹中 创建App:python manage.py startapp ocr
  3. 运行:python manage.py runserver
    在这里插入图片描述

二、前端项目vite+vue3

vite教程

  1. 根据需求创建项目npm create vite@latest ocr-excel-ui --template vue
    在这里插入图片描述
  2. 进入文件夹安装依赖:npm install
  3. 启动:npm run dev
    在这里插入图片描述

以下已用code打开项目

三、后端配置

3.1 将路由指向app
(此处app指ocr,使用python manage.py startapp ocr 创建 下不提示)

ocrEcxel/urls.py

from django.contrib import admin
from django.urls import path, includeurlpatterns = [path('admin/', admin.site.urls),path("api/", include("ocr.urls")),	# api为前端的接口路径
]
3.2 app下创建urls.py, 写入路由

此时app中并没有urls.py 所以需要新建,再写入代码
在这里插入图片描述

ocr/urls.py

from django.urls import pathfrom . import viewsurlpatterns = [path("test", views.test, name="index"),	# test路径 对应views中的test函数,看下一步
]
3.3 views写入test函数

ocr/views.py

from django.shortcuts import render
from django.http import HttpResponse# Create your views here.
def test(request):return HttpResponse("Test, HelloWorld.")	# 测试接口,这里直接返回一段话
3.4 启动服务,访问路由

python manage.py runserver
在这里插入图片描述

http://127.0.0.1:8000/api/test
在这里插入图片描述

到此后端接口基本通了,接下来配置前端项目

四、前端配置

4.1 安装一些工具库及创建文件
4.1.1 安装需要用的三方库
npm install element-plus 	# UI
npm install vue-router 		# 路由
npm install axios			# axios
npm install sass			# sass#或者
npm install element-plus vue-router axios sass

在这里插入图片描述

4.1.2 创建文件
> src > api			// 接口- index.js- request.js- status.js> module- test.js> assets		// 资源> svg> components	// 组件> Header- index.js> router		// 路由- index.js- routes.js> views			// 页面- index.vue

如图
在这里插入图片描述

4.2 配置、写代码
4.2.1 vite.config.js 参考
import { defineConfig } from 'vite'
import vue from '@vitejs/plugin-vue'
import path from 'path'// https://vitejs.dev/config/
export default defineConfig({plugins: [vue()],base: './',   // 在生产中服务时的基本公共路径publicDir: 'public',  // 静态资源服务的文件夹, 默认"public"resolve: {alias: {"@": path.resolve(__dirname, './src'), // 这里是将src目录配置别名为 @ 方便在项目中导入src目录下的文件"api": path.resolve(__dirname, './src/api'), // 这里是将src/api目录配置别名为 api 方便在项目中引入接口}},// 本地运行配置,及反向代理配置server: {host: '0.0.0.0', // 指定服务器主机名port: 3000, // 指定服务器端口open: true, // 在服务器启动时自动在浏览器中打开应用程序strictPort: false, // 设为 false 时,若端口已被占用则会尝试下一个可用端口,而不是直接退出https: false, // 是否开启 httpscors: true, // 为开发服务器配置 CORS。默认启用并允许任何源proxy: { // 为开发服务器配置自定义代理规则// 选项写法'/api': {target: 'http://127.0.0.1:8000', //代理接口changeOrigin: true,// rewrite: (path) => path.replace(/^\/api/, '')  // 重写路径}}}
})
4.2.2 src/main.js
import { createApp } from 'vue'
import './style.css'
import App from './App.vue'import ElementPlus from 'element-plus'
import 'element-plus/dist/index.css'
import zhCn from 'element-plus/es/locale/lang/zh-cn'import router from './router'const app = createApp(App)
app.use(ElementPlus, {local: zhCn}) // element-plus 国际化app.use(router) // 路由app.mount('#app')
4.2.3 请求封装 参考

src/api/request.js

import axios from 'axios';
import { showMessage } from "./status";   // 引入状态码文件
import { ElMessage } from 'element-plus'  // 引入el 提示框,这个项目里用什么组件库这里引什么// 设置接口超时时间
axios.defaults.timeout = 60000;//http request 拦截器
axios.interceptors.request.use(config => {// 配置请求头config.headers = {//'Content-Type':'application/x-www-form-urlencoded',   // 传参方式表单'Content-Type': 'application/json;charset=UTF-8',        // 传参方式json'token': '80c483d59ca86ad0393cf8a98416e2a1'              // 这里自定义配置,这里传的是token};return config;},error => {return Promise.reject(error);}
);//http response 拦截器
axios.interceptors.response.use(response => {return response;},error => {const { response } = error;if (response) {// 请求已发出,但是不在2xx的范围let message = showMessage(response.status);           // 传入响应码,匹配响应码对应信息ElMessage.warning(message);return Promise.reject(response.data);} else {ElMessage.warning('网络连接异常,请稍后再试!');}}
);// 封装 GET POST 请求并导出
export default function request(url = '', params = {}, type = 'POST') {//设置 url params type 的默认值return new Promise((resolve, reject) => {let promiseif (type.toUpperCase() === 'GET') {promise = axios({url,params})} else if (type.toUpperCase() === 'POST') {promise = axios({method: 'POST',url,data: params})}//处理返回promise.then(res => {resolve(res)}).catch(err => {reject(err)})})
}

src/api/status.js

export const showMessage = (status) => {let message = "";switch (status) {case 400:message = "请求错误(400)";break;case 401:message = "未授权,请重新登录(401)";break;case 403:message = "拒绝访问(403)";break;case 404:message = "请求出错(404)";break;case 408:message = "请求超时(408)";break;case 500:message = "服务器错误(500)";break;case 501:message = "服务未实现(501)";break;case 502:message = "网络错误(502)";break;case 503:message = "服务不可用(503)";break;case 504:message = "网络超时(504)";break;case 505:message = "HTTP版本不受支持(505)";break;default:message = `连接出错(${status})!`;}return `${message},请检查网络或联系管理员!`;
};

src/api/index.js

import test from './module/test.js'export default {...test,
}

src/api/module/test.js

import request from 'api/request'export default {/*** Test*/async testApi(params) {let url = `/api/test`;return await request(url, params, 'GET');},
}
4.2.4 页面菜单

src/components/Header/index.vue

<template><el-menu :default-active="activeIndex" class="el-menu-demo" mode="horizontal" :ellipsis="false" @select="handleSelect"><el-menu-item index="/"><img style="width: 100px" src="@/assets/svg/logo.svg" alt="Element logo" /></el-menu-item><div class="flex-grow" /><el-menu-item index="/about">Processing Center</el-menu-item><el-sub-menu index="/other"><template #title>Workspace</template><el-menu-item index="2-1">item one</el-menu-item><el-menu-item index="2-2">item two</el-menu-item><el-menu-item index="2-3">item three</el-menu-item><el-sub-menu index="2-4"><template #title>item four</template><el-menu-item index="2-4-1">item one</el-menu-item><el-menu-item index="2-4-2">item two</el-menu-item><el-menu-item index="2-4-3">item three</el-menu-item></el-sub-menu></el-sub-menu></el-menu>
</template><script lang="ts" setup>
import { ref } from 'vue'
import { useRouter } from 'vue-router'let router = useRouter();const activeIndex = ref('/') // 首页
const handleSelect = (key: string, keyPath: string[]) => {router.push(keyPath[0])	// 点击跳转
}
</script><style>
.flex-grow {flex-grow: 1;
}
</style>
4.2.5 页面

src/views/index.vue

<template><el-button @click="handleClick">请求test</el-button>
</template><script setup>
import api from 'api/index';let handleClick = async () => {let res = await api.testApi();console.log(res);
}
</script>
4.2.6 路由 参考

src/router/index.js

// 导入router所需的方法
import { createRouter, createWebHistory } from 'vue-router'// 导入路由页面的配置
import routes from './routes'// 路由参数配置
const router = createRouter({// 使用hash(createWebHashHistory)模式,(createWebHistory是HTML5历史模式,支持SEO)history: createWebHistory(),routes: routes,
})// 全局前置守卫,这里可以加入用户登录判断
router.beforeEach((to, from, next) => {// 继续前进 next()// 返回 false 以取消导航next()
})// 全局后置钩子,这里可以加入改变页面标题等操作
router.afterEach((to, from) => {const _title = to.meta.titleif (_title) {window.document.title = _title}
})// 导出默认值
export default router

src/router/routes

const routes = [{path: '/',name: 'index',title: '首页',component: () => import('@/views/index.vue'), //.vue不能省略}
]
export default routes
4.2.7 logo

logo
保存这个图标 放入src/assets/svg
在这里插入图片描述

4.2.8 App.vue

src/App.vue

<script setup>
import Header from '@/components/Header/index.vue'
</script><template><Header></Header><router-view />
</template><style scoped>
</style>
4.3 启动前端项目、测试接口联通性

npm run dev
在这里插入图片描述
浏览器打开,触发请求,成功返回
在这里插入图片描述

五、问题

5.1 跨域在这里插入图片描述
方法1:vite.config.js配置前端代理
 // 本地运行配置,及反向代理配置server: {host: '0.0.0.0', // 指定服务器主机名port: 3000, // 指定服务器端口open: true, // 在服务器启动时自动在浏览器中打开应用程序strictPort: false, // 设为 false 时,若端口已被占用则会尝试下一个可用端口,而不是直接退出https: false, // 是否开启 httpscors: true, // 为开发服务器配置 CORS。默认启用并允许任何源proxy: { // 为开发服务器配置自定义代理规则// 选项写法'/api': {target: 'http://127.0.0.1:8000', //代理接口changeOrigin: true,// rewrite: (path) => path.replace(/^\/api/, '')  // 重写路径}}}
方法2:后端解除限制

pip install django-cors-headers

MIDDLEWARE = ['django.middleware.security.SecurityMiddleware','django.contrib.sessions.middleware.SessionMiddleware','corsheaders.middleware.CorsMiddleware',    # 添加1,注意中间件的添加顺序'django.middleware.common.CommonMiddleware','django.middleware.csrf.CsrfViewMiddleware','django.contrib.auth.middleware.AuthenticationMiddleware','django.contrib.messages.middleware.MessageMiddleware','django.middleware.clickjacking.XFrameOptionsMiddleware',
]
CORS_ORIGIN_ALLOW_ALL = True  

在这里插入图片描述

5.2 不允许访问

DisallowedHost at /api/test
Invalid HTTP_HOST header: ‘10.102.88.76:3000’. You may need to add ‘10.102.88.76’ to ALLOWED_HOSTS.

在这里插入图片描述
解决:

方法1:在前端代理

vite.config.js中加上配置:changeOrigin: true,
在这里插入图片描述

方法2:在后端加入白名单

setting.py中的 ALLOWED_HOSTS数组中 加上自己IP或 ‘*’ (全部允许)
在这里插入图片描述

六、vue项目部署到Django

6.1 前端打包

npm run build
在这里插入图片描述
此时在项目中出现了打包后的dist文件夹
在这里插入图片描述

6.2 将打包好的文件夹放到django项目中
6.2.1 新建一个templates文件夹,放入前端打包文件

在这里插入图片描述

6.3 修改ocrExcel/urls.py
from django.contrib import admin
from django.urls import path, include
from django.views.generic import TemplateViewurlpatterns = [path('admin/', admin.site.urls),path("api/", include("ocr.urls")),	# api为前端的接口路径path('', TemplateView.as_view(template_name="index.html")), # 
]
6.4 修改setting.py
6.4.1 找到TEMPLATES,在DIRS中加入os.path.join(BASE_DIR, 'templates/dist')

如下

TEMPLATES = [{'BACKEND': 'django.template.backends.django.DjangoTemplates','DIRS': [os.path.join(BASE_DIR, 'templates/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',],},},
]
6.4.2 找到STATIC_URL,修改

STATIC_URL = 'static/' 修改为: STATIC_URL = 'assets/'
再加个配置,总体如下

STATIC_URL = 'assets/' # 注意静态文件的路径
STATICFILES_DIRS = [os.path.join(BASE_DIR, "templates/dist/assets"),    # 添加2,注意静态文件的路径
]
6.5 启动Django

python manage.py runserver
访问:出现了页面
在这里插入图片描述
发送一个请求试试:
在这里插入图片描述
成功了,顺利返回

就这样结束了吗?还没有,还有个坑,这时候我们点击菜单的“Processing Center”,到 http://127.0.0.1:8000/about
可以正常跳转过来
在这里插入图片描述

但是,如果这时候刷新页面会出现什么呢?
在这里插入图片描述
怎么一刷新页面就404了
因为vue是单页面应用,这时候在/about下刷新页面,django会认为这是一个后端请求,而urls.py中又找不到相应的路由,就报了404

解决方式就是修改一下6.3步的urls.py 文件

"""
from django.contrib import admin
from django.urls import path, include, re_path
from django.views.generic import TemplateViewurlpatterns = [path('admin/', admin.site.urls),path("api/", include("ocr.urls")),	# api为前端的接口路径re_path("", TemplateView.as_view(template_name="index.html")),	# vue是单页面应用,将其余所有路由转到vue
]

将所有非admin、api开头的请求都转到vue,就可以自由刷新页面了,这样也存在一个问题,就是后端没有404的情况了,这就需要交给前端处理。创建一个404的页面,前端没有路由时重定向到404页面。

结语

就先到这里吧,架子搭好,开始写代码了,后面遇到什么问题再更新

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.mzph.cn/news/201227.shtml

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

Nacos 服务注册与发现

一、Spring Cloud Commons 二、使用方法 &#xff08;1&#xff09;在cloud-demo父工程中添加spring-cloud-alilbaba的管理依赖 &#xff08;2&#xff09;注释掉order-service和user-service中原有的eureka依赖 &#xff08;3&#xff09;添加nacos的客户端依赖 &#xff08;4…

Mysql学习查缺补漏----02 mysql之DCL 数据控制语言

查看数据库里都有哪些用户。 使用root任何一个用户都可以登录。 本机登录。 也可以这样登录其他的机器。 、 修改user表。 刷新权限&#xff1a; 现在我们看到了只有本机才能登陆。 我们这样就可以限制这个mysql指定某台服务器登录。 详解忘记密码以及如何修改用户密码 我们…

华为全面对标iOS,“纯血鸿蒙”时代来了

原创 | 文 BFT机器人 就在今年的10月份&#xff0c;华为官方宣布&#xff0c;鸿蒙OS 4升级设备数量已经突破1亿&#xff0c;成为史上升级最快的鸿蒙OS版本。 伴随着“Harmony OS NEXT”的启动&#xff0c;鸿蒙系统开发者社区迎来了喜讯——新增注册开发者数量已过万&#xff0…

C++ 命名空间详解

目录 引入例子 命名空间的定义 命名空间的使用 命名空间使用注意事项 引入例子 #include <stdio.h> #include <stdlib.h>int rand 10;int main() {printf("%d\n", rand);return 0; } 当我们用C语言写下这样的代码&#xff0c;看着并没有什么语法问…

AI助力智慧农业,基于YOLOv5全系列模型【n/s/m/l/x】开发构建不同参数量级农田场景下庄稼作物、杂草智能检测识别系统

紧接前文&#xff0c;本文是农田场景下庄稼作物、杂草检测识别的第二篇文章&#xff0c;前文是基于YOLOv3这一网络模型实现的目标检测&#xff0c;v3相对来说比较早期的网络模型了&#xff0c;本文是基于最为经典的YOLOv5来开发不同参数量级的检测端模型。 首先看下实例效果&a…

介绍一款在线文件格式转换工具

原因: 今天要将一个pdf格式的文件转为docx格式,结果我用破解版的WPS无法再不登录的情况下转换,所以就搜索了一款在线工具实现功能。 网站地址: Convertio — 文件转换器 使用流程: 1)选择要转换的文件 2)选择要转换的格式 3)点击转换 4)等待上传 5)等待转换 6)下载到本地

Linux简单部署Yearning并结合内网穿透工具发布至公网可访问

目录 前言 1. Linux 部署Yearning 2. 本地访问Yearning 3. Linux 安装cpolar 4. 配置Yearning公网访问地址 5. 公网远程访问Yearning管理界面 6. 固定Yearning公网地址 前言 Yearning 简单, 高效的MYSQL 审计平台 一款MYSQL SQL语句/查询审计工具&#xff0c;为DBA与开发…

Vue混淆与还原

Vue混淆与还原 引言 Vue是一种流行的JavaScript框架&#xff0c;用于构建用户界面。它简单易用且功能强大&#xff0c;备受开发者喜爱。然而&#xff0c;在传输和存储过程中&#xff0c;我们需要保护Vue代码的安全性。混淆是一种有效的保护措施&#xff0c;可以加密和压缩代码…

Course2-Week1-神经网络

Course2-Week1-神经网络 文章目录 Course2-Week1-神经网络1. 神经网络概述1.1 欢迎来到Course21.2 神经元和大脑1.3 引入神经网络-需求预测1.4 神经网络的其他示例-图像感知 2. 神经网络的数学表达式2.1 单层的神经网络-需求预测2.3 前向传播的神经网络-手写数字识别 3. Tensor…

学生护眼台灯怎么样选择?适合考研的护眼台灯推荐

很多家长都是为了孩子的视力健康而置换的护眼台灯&#xff0c;但是有一部分孩子用了之后反而会和家长说出现眼睛不太舒服&#xff0c;甚至近视加深的情况。而引发这种情况的大多数为产品不达标或非专业台灯&#xff0c;因为专业护眼台灯是真实能够保护眼睛的。 所以很多人都对护…

文件上传漏洞(带实例)

漏洞介绍&#xff1a; 现代互联网的Web应用程序中&#xff0c;上传文件是一种常见的功能&#xff0c;因为它有助于提高业务效率&#xff0c;如企业的OA系统&#xff0c;允许用户上传图片&#xff0c;视频&#xff0c;头像和许多其他类型的文件。然而向用户提供的功能越多&#…

【Polar靶场WEB签到】

题目&#xff1a; <?phperror_reporting(0);$file $_GET[file];if(!isset($file))$file 1;$file str_replace(../, , $file);include_once($file.".php");highlight_file(__FILE__); ?>解答&#xff1a;1、进入index页面&#xff0c;说让你加弟弟&#x…

ArcGIS平滑处理栅格数据

一、实验背景 基于栅格数据的空间分析&#xff0c;常常需要根据特定的分析场景对栅格数据进行处理&#xff0c;如栅格数据的噪声处理。噪声是属性值具有突跃特征的像元位置&#xff0c;直接对带有噪声的栅格数据进行分析会对结果造成较大的影响。而降噪的主要方法之一是平滑&a…

会议剪影 | “聚势合力 共创高峰”2023思腾合力成都客户答谢会圆满结束

2023年11月29日至12月1日&#xff0c;以“聚势合力 共创高峰”为主题的思腾合力成都答谢会&#xff0c;在成都都江堰皇冠假日酒店盛大举行&#xff0c;来自各地的客户齐聚于此&#xff0c;共同见证思腾合力的成长与突破&#xff0c;展望未来的合作与发展。 思腾合力总经理王伟热…

2024面试必备的MySQL基础初级面试文集。

&#x1f3c6;作者简介&#xff0c;普修罗双战士&#xff0c;一直追求不断学习和成长&#xff0c;在技术的道路上持续探索和实践。 &#x1f3c6;多年互联网行业从业经验&#xff0c;历任核心研发工程师&#xff0c;项目技术负责人。 &#x1f389;欢迎 &#x1f44d;点赞✍评论…

Opencv获取当前视频长宽、总帧数、fps

Opencv提供了类似java中静态变量的参数&#xff0c;可以通过get(参数)获取当前视频的信息&#xff0c;参数类别还是挺多的&#xff0c;按照需求查手册或源码即可。 源码参数举例 获取视频帧的长宽 import cv2 if __name__ __main__:mp4_path xhx_utils/images/demo.mp4video…

【hacker送书第9期】算法训练营(入门篇)

第9期图书推荐 内容简介作者简介精彩书评图书目录概述参与方式 内容简介 本书以海量图解的形式&#xff0c;详细讲解常用的数据结构与算法&#xff0c;又融入大量的竞赛实例和解题技巧。通过对本书的学习&#xff0c;读者可掌握12种初级数据结构、15种常用STL函数、10种二叉树和…

C程序的内存布局分析

C 程序的典型内存由以下部分组成&#xff1a; 文本段&#xff08;text&#xff09;初始化数据段 &#xff08;data&#xff09;未初始化数据段&#xff08;bss&#xff09;堆 &#xff08;heap&#xff09;栈&#xff08;stack&#xff09; 典型内存布局&#xff1a; 1.文本段…

Java 控制台命令导入本地jar包到maven本地库中

1、新建POM文件&#xff0c;在maven库路径下创建POM文件 注意&#xff1a;这个路径需要与第2点导入命令中的grouoId、artifactId和version写法对应 Path&#xff1a;D:\RomanData\repository\com\sae\mail\1.0.0\mail-1.0.0.pom <?xml version"1.0" encoding&q…

基于web的ssm邮票鉴赏系统源码和论文

网络的广泛应用给生活带来了十分的便利。所以把邮票鉴赏管理与现在网络相结合&#xff0c;利用java技术建设邮票鉴赏系统&#xff0c;实现邮票鉴赏的信息化。则对于进一步提高邮票鉴赏管理发展&#xff0c;丰富邮票鉴赏管理经验能起到不少的促进作用。 邮票鉴赏系统能够通过互…