【无标题】从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.rhkb.cn/news/214974.html

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

相关文章

尝试通过AI模型进行简单的编码

一、前言 最近尝试通过AI来编程&#xff0c;总体感觉还是能处理写简单的问题&#xff0c;复杂的问题目前还是无法解决。主要的痛点还是数据噪音&#xff0c;就是AI永远不会承认它不会&#xff0c;它会给你的一个错误的信息&#xff0c;它也不会告诉你你的问题它暂时无法完整正…

JUC并发编程03——LockSupport与线程中断

一.线程中断机制 假设从网络下载一个100M的文件&#xff0c;如果网速很慢&#xff0c;用户等得不耐烦&#xff0c;就可能在下载过程中点“取消”&#xff0c;这时&#xff0c;程序就需要中断下载线程的执行。 1.1如何停止中断运行中的线程&#xff1f; 通过一个volatile变量…

智能优化算法应用:基于郊狼算法3D无线传感器网络(WSN)覆盖优化 - 附代码

智能优化算法应用&#xff1a;基于郊狼算法3D无线传感器网络(WSN)覆盖优化 - 附代码 文章目录 智能优化算法应用&#xff1a;基于郊狼算法3D无线传感器网络(WSN)覆盖优化 - 附代码1.无线传感网络节点模型2.覆盖数学模型及分析3.郊狼算法4.实验参数设定5.算法结果6.参考文献7.MA…

ES6原生音乐播放器(有接口)

视频展示 ES6音乐播放器 项目介绍 GutHub地址&#xff1a;GitHub - baozixiangqianchong/ES6_MusicPlayer: 音乐播放器 ES6_MusicPlayer 是基于JavaScriptES6Ajax等通过原生构建的项目。能够充分锻炼JS能力。 本项目有主页、详情页、歌单页面三部分组成 ├── assets&…

Visual Studio 2022+Python3.11实现C++调用python接口

大家好&#xff01;我是编码小哥&#xff0c;欢迎关注&#xff0c;持续分享更多实用的编程经验和开发技巧&#xff0c;共同进步。 查了一些资料&#xff0c;不是报这个错&#xff0c;就是报哪个错&#xff0c;没有找到和我安装的环境的一致的案例&#xff0c;于是将自己的摸索分…

HHDESK右键管理简介

在HHDESK管理文件&#xff0c;除了基本的打开、删除、复制、粘贴、重命名外&#xff0c;还有多种便捷编辑方式。 可以分别以下列模式打开文档&#xff1a; 文本模式即是以文本编辑器打开文档。 1 二进制模式 可进行二进制编辑。 2 JSON模式 可对JSON文件进行直观的解析…

用户登录权限

文章目录 [TOC](文章目录) 前言一、鉴权二、 Cookie与session1.HTTP无状态2.cookie的重要属性3.cookie 和 session 的生命周期3.1 cookie 生命周期影响因素3.2 session 生命周期影响因素 4.cookie 和 session 的区别5.工作原理3 用户登录Node.js和Express验证session 三、JSON …

LinuxBasicsForHackers笔记 -- 管理用户环境变量

查看和修改环境变量 env – 您可以通过从任何目录在终端中输入 env 来查看所有默认环境变量。环境变量的名称始终为大写&#xff0c;如 HOME、PATH、SHELL 等。 查看所有环境变量 set – 查看所有环境变量&#xff0c;包括 shell 变量、局部变量和 shell 函数&#xff08;例…

记一次测试环境git翻车经历

本来想拉一个功能分支进行新的功能开发&#xff0c;合并代码发现没有冲突居然有文件被修改了&#xff0c;贸然选择最近的一次回滚提交&#xff0c;没想到不假思索的push -f 导致一部分dev主干的代码不见了。 事故记录 开发分支origin/dev&#xff0c;功能分支file 合并之后发…

UE Websocket笔记

参考链接 [UE4 C入门到进阶]12.Websocket网络通信 - 哔哩哔哩 包含怎么用Nodejs 写测试服务器 UE4_使用WebSocket和Json&#xff08;上&#xff09; - 知乎 包含Python写测试服务器 UE4_使用WebSocket和Json&#xff08;下&#xff09; - 知乎 示例代码 xxx.Build.cs"W…

带有 RaspiCam 的 Raspberry Pi 监控和延时摄影摄像机

一、说明 一段时间以来&#xff0c;我一直想构建一个运动激活且具有延时功能的树莓派相机&#xff0c;但从未真正找到我喜欢的案例。我在thingiverse上找到了这个适合树莓派和相机的好案例。它是为特定的鱼眼相机设计的&#xff0c;但从模型来看&#xff0c;我拥有的廉价中国鱼…

重温经典struts1之常用标签

提示&#xff1a;文章写完后&#xff0c;目录可以自动生成&#xff0c;如何生成可参考右边的帮助文档 前言 上一篇&#xff0c;我们学习了struts的基本概念&#xff0c;怎样搭建struts开发环境&#xff0c;从编写formbean&#xff0c;action到jsp页面&#xff0c;以及怎样将他…

Flink之流的转换

ProcessFuncion处理函数 功能 拥有富函数功能 - 生命周期方法 - 状态编程对元素的处理功能processElement, 在不同的处理函数中&#xff0c;该方法的名字略有区别定时器编程 TimeService:定时服务,可以用于注册定时器&#xff0c;删除定时器ontimer():定时器触发后会自动调用该…

C++中字符串详解

在C语言中只能通过字符串数组来模拟字符串&#xff0c;没有字符串类型。在C引入了string类来表示字符串类型。从而用它定义字符串。 在C语言中&#xff1a; char str[] "abc"; char str[] {a&#xff0c;b,c,\0}; char* str "abc"; //这三种形式是C语言…

Java TCP(一对一)聊天简易版

客户端 import java.io.*; import java.net.Socket; import java.util.Date; import javax.swing.*;public class MyClient {private JFrame jf;private JButton jBsend;private JTextArea jTAcontent;private JTextField jText;private JLabel JLcontent;private Date data;p…

推荐一个FL Studio最适配的midi键盘?

Hello大家好&#xff01;好消息&#xff01;好消息&#xff01;特大好消息&#xff01; 水果党们&#xff01;终于有属于自己的专用MIDI键盘啦&#xff01; 万众期待的Novation FLKEY系列 正式出炉&#xff01; 做编曲和音乐制作的朋友们&#xff0c;对水果软件FLSTUDIO应该…

使用xshell连接虚拟机(服务器)

作者&#xff1a;余小小 Xshell Xshell [1] 是一个强大的安全终端模拟软件&#xff0c;它支持SSH1, SSH2, 以及Microsoft Windows 平台的TELNET 协议。Xshell 通过互联网到远程主机的安全连接以及它创新性的设计和特色帮助用户在复杂的网络环境中享受他们的工作。 Xshell可以…

2023年度盘点:智能汽车、自动驾驶、车联网必读书单

【文末送书】今天推荐几本自动驾驶领域优质书籍 前言 2023年&#xff0c;智能驾驶和新能源汽车行业仍然有着肉眼可见的新进展。自动驾驶技术继续尝试从辅助驾驶向自动驾驶的过渡&#xff0c;更重要的是相关技术成本的下降。根据《全球电动汽车展望2023》等行业报告&#xff0c…

vue-baidu-map实现在地图上选择范围并解决相关问题

vue-baidu-map实现在地图上选择范围并解决相关问题 实现地图上选择不规则范围实现功能遇到的问题1、覆盖物多边形怎么才能盖住覆盖物点2、遇到其他问题 实现地图上选择不规则范围 这个功能比较简单&#xff0c;只需要使用vue-baidu-map插件的覆盖物多边形功能就行了。直接看文…

dToF直方图之美_激光雷达多目标检测

直方图提供了一种简单有效的方法来分析信号分布并识别与目标存在相对应的峰值,并且能够可视化大量数据,让测距数形结合。在车载激光雷达中,对于多目标检测,多峰算法统计等,有着区别于摄像头以及其他雷达方案的天然优势。 如下图,当中有着清晰可见的三个峰值,我们可以非…