前言
感覺有很多東西,不知道寫什么,隨便寫點吧。
正文
前后端合并
就不說怎么開發的,就說點個人感覺重要的東西。
前端用React+Vite+axios隨便寫一個demo,用于CRUD。
后端用Django REST Framework。
設置前端打包
import { defineConfig } from 'vite'
import react from '@vitejs/plugin-react'// https://vite.dev/config/
export default defineConfig({plugins: [react()],base:'./',build:{outDir:'template',assetsDir:'static',},server:{proxy:{'/api':{target:'http://localhost:8000',changeOrigin:true,rewrite:path=>path.replace(/^\/api/,'')}}}
})
如果不用一些代理工具nginx等,打包后代理沒有用了。
要么在axios中去掉
baseUrl='/api'
或者在Django的路由前加上/api,一樣,都行
后續操作
1、打包后將tempate目錄復制到Django的根目錄下
2、將vite.svg圖標放到static目錄下
3、修改settings.py文件的關鍵部分
TEMPLATES = [{'BACKEND': 'django.template.backends.django.DjangoTemplates','DIRS': [BASE_DIR/'templates'],'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',],},},
]
STATICFILES_DIRS=[BASE_DIR/'templates/static'
]
如果選擇static文件夾拿到根目錄,也行,修改一下STATICFILES_DIRS。
4、修改index.html,顯示圖標
{% load static %}
<!doctype html>
<html lang="en"><head><meta charset="UTF-8" /><link rel="icon" type="image/svg+xml" href="{% static 'vite.svg'%}" /><meta name="viewport" content="width=device-width, initial-scale=1.0" /><title>Vite + React</title><script type="module" crossorigin src="../static/index-CetNvwB0.js"></script><link rel="stylesheet" crossorigin href="../static/index-B7i0P6ID.css"></head><body><div id="root"></div></body>
</html>
5、修改項目的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/book/', include('book.urls')), # 加上api前綴re_path(r'^.*$', TemplateView.as_view(template_name='index.html')), # 這里是為了解決前端路由問題
]
啟動項目。
刷新頁面,沒有問題。
如果寫成下面這種。
path('',TemplateView.as_view(template_name='index.html')),
刷新就會報錯。因為前端路由和后端路由并不是完全相同的。
比如前端路由/show,而后端只有book,book/:id等的路由,沒有/show,路由不一致。
因此,代碼如下
re_path(r'^.*$', TemplateView.as_view(template_name='index.html'))
前后端合并完成,其實這個時候,可以部署到服務器。筆者選擇打包成exe文件
打包exe文件
筆者的Django項目是Rye建立的,安裝Pyinstaller
其中pyproject.toml的腳本內容如下
[tool.rye.scripts]dev = "python manage.py runserver"
build="pyinstaller -F manage.py"
build_add_data='pyinstaller -F --add-data="./templates;templates" --add-data="./static;static" manage.py'
dev :運行項目
build_add_data:增加其他模板文件和靜態文件打包成一個exe文件
筆者依照腳本移動templates目錄下的static到根目錄,為了更好的打包。也可以不移動,修改一下腳本的路徑即可。
筆者參考了其他大佬的打包過程,可能版本發生變換,打包簡單多了,只需要增加靜態文件和模板。
Pyinstaller打包Django項目(耗時兩天 踩坑無數 記錄一下)_runtimeerror: script runserver does not exist.-CSDN博客https://blog.csdn.net/qq_40292262/article/details/117026558pyinstaller打包Django項目+避坑指南-CSDN博客
https://blog.csdn.net/weixin_37934258/article/details/130216656進入到manage.py目錄下。
運行腳本
rye run build_add_data
雖然過程中有警告
但無所謂,運行成功。
完美。
后端打包,前端使用nw
在前篇文章中
在github action工作流使用nw和nw-builder打包-CSDN博客https://blog.csdn.net/qq_63401240/article/details/146126489?spm=1001.2014.3001.5502我使用了nw,nw可以吧html頁面打包成exe
筆者有個想法
不把前后端合并,后端沒有模板和靜態文件,就提供API,把后端打包成manage.exe
然后nw運行html文件時,同時打開manage.exe。
可惜,沒完全實現,筆者實力不行
前端打包和跨域問題
筆者可能剛剛知道nw,不是很了解,筆者發現需要html文件本身能夠運行,才能使用nw。
因此,修改路由為Hash
即createHashRouter,
如果不改,運行是這樣的
修改后
沒有顯示內容,因為代理失效了。
修改axios的baseUrl內容
import axios from 'axios';// 后端服務地址
const API_BASE_URL = 'http://127.0.0.1:8000/api';
const requests = axios.create({baseURL: API_BASE_URL, // 動態設置 baseURLtimeout: 5000,headers: {'Content-Type': 'application/json'}
});export default requests;
再次前端打包,運行
需要跨域,而筆者沒有使用代理工具。因此,筆者使用django-cors-headers
修改setting.py的配置
INSTALLED_APPS = [...'corsheaders', # 增加corsheaders
]
MIDDLEWARE = ['corsheaders.middleware.CorsMiddleware', # 配置中間件...]
CORS_ALLOW_ALL_ORIGINS = True # 允許所有的源訪問
運行index.html
后端打包
不需要模板和靜態文件
rye run build
打包沒有問題,不必細說。
后端、前端、nw合并
1、將沒有模板和靜態文件的manage.exe復制在前端pubilc目錄下
2、在前端pubilc目錄下新建package.json,內容如下
{"name": "book","version": "1.0.0","main": "index.html","window": {"icon": "vite.svg"},"scripts": {"dev": "concurrently \"node ./main.js\" \"nwbuild --mode=run --glob=false ./\"","nw:build": "nwbuild --mode=build --glob=false --output=../build ."},"dependencies": {"nw": "^0.96.0","nw-builder":"^4.13.9"},"devDependencies": {"concurrently": "^6.2.1"}
}
3、新建main.js文件,這里面deepseek寫的,我希望使用js代碼運行manage.exe
其中內容如下。
const { exec } = require('child_process');
const path = require('path');// 獲取 manage.exe 的路徑
const manageExePath = path.join(__dirname, 'manage.exe');// 打印路徑以調試
console.log('manageExePath:', manageExePath);// 在 Windows 上使用 start 命令啟動 manage.exe
if (process.platform === 'win32') {exec(`start "" "${manageExePath}" runserver --noreload`, (error, stdout, stderr) => {if (error) {console.error(`啟動 manage.exe 失敗: ${error.message}`);return;}console.log(`stdout: ${stdout}`);console.error(`stderr: ${stderr}`);});
} else {// 非 Windows 系統使用 spawnconst manageProcess = spawn(manageExePath, ['ruanserver', '--noreload'], {detached: true,stdio: 'ignore'});manageProcess.unref();manageProcess.on('close', (code) => {console.log(`manage.exe 退出,代碼 ${code}`);});manageProcess.on('error', (error) => {console.error(`啟動 manage.exe 失敗: ${error.message}`);});
}
安裝依賴后,運行dev腳本,同時運行manage.exe和nw
結果如下
完美
可惜
可惜,筆者并不知道如何打包后雙擊的同時運行manage.exe,這可能需要nw的知識,以后再來。