尧图网络科技YAOTU DIGITAL 获取报价
获取报价
首页 / 资讯中心 / 文章详情

前后端分离微信小程序全栈开发:Django+Vue+MySQL实战指南

发布时间:2026/9/26 11:47:26

资讯中心
01
ARTICLE

前后端分离微信小程序全栈开发:Django+Vue+MySQL实战指南

前后端分离微信小程序全栈开发:Django+Vue+MySQL实战指南
简介一套面向计算机专业毕业设计场景的家庭大厨微信小程序完整工程后端基于Python Django前端使用Vue小程序端采用微信开发者工具数据库选用MySQL整体前后端分离便于拆分学习与二次开发。系统覆盖用户与店铺注册登录、菜品信息及分类管理、购买菜品、订单行管理、管理员后台等模块并贯穿可行性分析、功能设计与数据库设计的完整思路从业务设计到数据落库形成闭环工程参考价值较强。包内共718个文件以Vue组件、Python后端脚本、微信小程序页面、图片样式资源为主同时包含SQL数据库脚本、毕业论文文档、运行安装批处理以及MP4视频教程压缩包整体44.78MB目录结构与源码层级清晰可快速定位前端页面、业务接口和数据库表。已有194人学习下载适合需要完整毕设源代码、数据库设计文档和操作演示视频的开发者参考使用。1. 家庭大厨小程序先想清楚它到底在做什么“微信小程序 Django Vue MySQL 前后端分离开发的家庭大厨小程序”这类毕业设计表面上是一个全栈课设题实际动手后你会发现最花时间的不是写页面也不是写接口而是把小程序、Vue 后台、Django API、MySQL 四个进程真正拉通。真机才能调的接口、Vite 代理、数据库编码、跨域预检任何一个都能卡住大半天。这篇文章按“数据模型 → Django → Vue → 小程序 → 联调避坑”的顺序把每一步该做什么、参数怎么设、失败看哪里讲清楚。适合拿这套题目做毕设的同学也适合想快速上手前后端分离项目实战的开发者参考。2. 前后端分离的数据底座表结构设计与数据库脚本导入2.1 四个进程与一条数据链为什么 Django 是唯一的 API 出口家庭大厨小程序按前后端分离来拆运行时一共有四个进程微信小程序客户端、Vue 管理后台、Django 后端服务、MySQL 数据库。小程序和 Vue 后台都不直接连数据库所有数据操作都走 Django 暴露的 REST API这是前后端分离项目实战里最基本的一条约定。数据流向是这样的小程序用户打开首页wx.request 请求 Django 的菜品列表接口Django 用 ORM 查 MySQL把结果序列化成 JSON 返回管理员在 Vue 后台新增菜品Vue 把表单数据 POST 给 Django 的管理接口Django 再写库。两边共用同一套 API只是接口权限不同。小程序端是普通用户权限Vue 后台需要管理员登录态。拿到这套题目的源码包之后别急着打开代码先按这个结构检查项目目录后端 Django 工程、前端 Vue 工程、小程序原生工程、数据库脚本、论文。确认五个部分都在再开始配环境。数据库脚本是第一个要跑通的东西因为它决定了后面所有接口能不能查到数据。2.2 数据模型拆分家庭大厨需要的 7 张核心表家庭大厨的业务围绕“菜谱”展开数据模型按最小可用来拆七张核心表就够了。用户表存微信用户信息分类表存菜系或场景家常菜、凉菜、汤羹、早餐等菜品表存菜名、做法步骤、封面图食材表存常用食材菜品食材关联表解决“一道菜用多种食材、一种食材出现在多道菜”的多对多关系收藏表和评论表分别记录用户行为和互动内容。表名用途关键字段user_profile小程序微信用户openid、昵称、头像、注册时间category菜品分类分类名、排序值、图标recipe菜品主表菜名、封面图、做法步骤、难度、时长、分类外键ingredient食材表食材名称、常见单位recipe_ingredient菜品食材关联菜品外键、食材外键、用量favorite收藏记录用户外键、菜品外键、收藏时间comment评论表用户外键、菜品外键、内容、评分这张表结构参考了很多菜谱类小程序的设计没有过度抽象胜在简单直接。用户表单独建而不是直接复用 Django 自带的 User 表是为了让 openid 和昵称头像这类微信字段有地方放也避免和后台管理员的账号体系混在一起。菜品和分类是一对多分类删除时菜品要处理实际开发里一般做软删除或者限制删除。2.3 从 SQL 脚本到 Django models导入数据库脚本的三种姿势题目里带了数据库脚本最常见的形式是一个 .sql 文件。导入到 MySQL 的命令很简单但很多人第一次执行就报错。先确保 MySQL 服务已经启动然后用命令行导入mysql -u root -p -e CREATE DATABASE IF NOT EXISTS familychef DEFAULT CHARACTER SET utf8mb4 COLLATE utf8mb4_unicode_ci; mysql -u root -p familychef database.sql第一条命令建库并指定 utf8mb4 字符集第二条命令把脚本里的建表和插入语句执行到 familychef 库。这里有两个关键参数utf8mb4 是必须的因为小程序端会提交 emoji 表情和中文昵称用老旧的 utf8mb3 会报 Incorrect string value导入时如果出现乱码在第二条命令前面加 --default-character-setutf8mb4 重试。如果你的机器上没装 mysql 命令行工具也可以在 Navicat 或 MySQL Workbench 里直接运行 .sql 文件。还有第三种姿势把 SQL 脚本转换成 Django migration。常见做法是先按脚本里的表结构写好 models然后让 Django 的 makemigrations 生成迁移文件再 migrate 到新库。这样做的优点是 models 和数据库强一致缺点是原脚本里的初始数据要另外导入。我一般建议毕设阶段直接用原脚本建库然后把 models 的表名和字段名对齐脚本两边保持一致即可。2.4 字符集与时间字段两个最容易埋雷的建表参数建表脚本里有几个参数值得单独说。第一个是时间字段的类型推荐用 datetime 而不是 timestamp。timestamp 的范围到 2038 年而且会跟着数据库时区走Django 写入的 naive datetime 和 MySQL 的会话时区不一致时查出来的时间可能差八个小时。用 datetime 存的是字面值前端显示什么就是什么。第二个是金额和评分字段。如果菜品要做价格或者评分用 Decimal(5,2) 而不是 Float。Float 在 MySQL 里是近似值评分 4.8 存进去可能变成 4.799999...接口返回给小程序后前端没法直接做比较。Decimal 是精确值排序和筛选都稳定。第三个是排序值字段category 表和 recipe 表里都建议加一个 sort_order 整型字段默认 0。列表接口按 sort_order 升序、id 降序排列管理员在 Vue 后台调整排序时只需要改这个数字不用动表结构。很多毕设代码里省略了这个字段导致后台不能调顺序真做起来才发现不够用。提示导入脚本后用 mysql 客户端执行 SHOW CREATE TABLE recipe; 检查一下表注释和自增主键有没有生成。有的脚本导出时带着 DROP TABLE IF EXISTS执行前确认你库里的旧表可以删除。3. Django 后端把菜谱接口变成可调用的 REST API3.1 项目脚手架django-admin 与 app 拆分Django 后端是整个系统的 API 出口我习惯按业务拆成两个 app一个负责用户认证一个负责菜谱业务。先建项目和 apppip install django djangorestframework django-cors-headers PyJWT mysqlclient django-admin startproject familychef_backend cd familychef_backend python manage.py startapp user_auth python manage.py startapp recipe依赖里 mysqlclient 是让 Django 连 MySQL 的驱动Windows 上经常装不上。如果 pip install 失败可以用 pymysql 替代在 settings.py 里加两行import pymysql pymysql.install_as_MySQLdb()但要注意pymysql 的性能和兼容性在 Python 3.10 下偶尔有坑毕设规模完全够用。app 拆成 user_auth 和 recipe规则很简单和微信登录、用户资料有关的放 user_auth和分类、菜品、收藏、评论有关的放 recipe。不要把所有代码堆进一个 app论文里画系统架构图的时候也更容易说清楚。3.2 settings.py 里必须写对的四组配置连接 MySQL、配置跨域、注册 app、设置 media 路径这几组配置缺一个后端就跑不起来。下面是一份能直接用的配置片段INSTALLED_APPS [ django.contrib.admin, django.contrib.auth, django.contrib.contenttypes, django.contrib.sessions, django.contrib.messages, django.contrib.staticfiles, rest_framework, corsheaders, user_auth, recipe, ] MIDDLEWARE [ corsheaders.middleware.CorsMiddleware, django.middleware.common.CommonMiddleware, ] DATABASES { default: { ENGINE: django.db.backends.mysql, NAME: familychef, USER: root, PASSWORD: 你的数据库密码, HOST: 127.0.0.1, PORT: 3306, OPTIONS: { charset: utf8mb4, init_command: SET sql_modeSTRICT_TRANS_TABLES, }, } } CORS_ALLOW_ALL_ORIGINS True MEDIA_URL /media/ MEDIA_ROOT BASE_DIR / mediaCORS_ALLOW_ALL_ORIGINS 开发阶段设成 True 最省事Vue 后台在 localhost:5173 请求 Django 的 8000 端口就不会被浏览器拦截。charset 指定 utf8mb4否则 Django 写入的中文和 emoji 会乱码。MEDIA_ROOT 是上传图片落盘的目录urls.py 里要追加 static 路由才能通过 URL 访问。3.3 用 DRF 序列化器把 Recipe 变成 JSONDjango 的 ORM 查出来的是 QuerySet不能直接返回给小程序。DRF 的 ModelSerializer 把数据转成 JSON同时承担字段校验的工作。以菜品为例# recipe/serializers.py from rest_framework import serializers from .models import Recipe, Category class CategorySerializer(serializers.ModelSerializer): class Meta: model Category fields [id, name, sort_order] class RecipeListSerializer(serializers.ModelSerializer): category_name serializers.CharField(sourcecategory.name, read_onlyTrue) class Meta: model Recipe fields [id, name, cover_image, duration, difficulty, category_name] read_only_fields fields注意 category_name 这个字段它从关联的 Category 表里取 name序列化成字符串小程序端拿到之后直接展示不需要再发起一次分类查询。fields 里明确列出要返回的字段不要在 Meta 里直接写 fields all否则密码、内部备注这类敏感字段很容易漏出去。视图用 DRF 的 APIView 或者 ViewSet 都可以。毕设规模用 ViewSet 加 router 最省代码# recipe/views.py from rest_framework import viewsets from .models import Recipe, Category from .serializers import RecipeListSerializer, CategorySerializer class CategoryViewSet(viewsets.ReadOnlyModelViewSet): queryset Category.objects.filter(statusTrue).order_by(sort_order) serializer_class CategorySerializer class RecipeViewSet(viewsets.ReadOnlyModelViewSet): queryset Recipe.objects.filter(statusTrue).order_by(-id) serializer_class RecipeListSerializer def get_queryset(self): qs super().get_queryset() category_id self.request.query_params.get(category) if category_id: qs qs.filter(category_idcategory_id) return qsReadOnlyModelViewSet 只提供列表和详情两个动作用在小程序端的公开接口上很合适不需要暴露 POST 和 DELETE。get_queryset 里做的 category 筛选对应小程序分类页点击某个分类后按分类 ID 拉取菜品列表的逻辑。3.4 登录认证小程序 code2session 与 JWT 签发小程序端没有传统的账号密码登录流程是小程序调用 wx.login 拿到临时 code传给 DjangoDjango 用 code 换 openid再用 openid 签一个 JWT 返回给小程序。后续请求都把 JWT 放在 Authorization 头里。核心代码# user_auth/views.py import requests, jwt, time from django.conf import settings from rest_framework.views import APIView from rest_framework.response import Response from .models import UserProfile class WxLoginView(APIView): def post(self, request): code request.data.get(code) if not code: return Response({code: 400, msg: 缺少 code}, status400) url https://api.weixin.qq.com/sns/jscode2session params { appid: settings.WX_APPID, secret: settings.WX_SECRET, js_code: code, grant_type: authorization_code, } resp requests.get(url, paramsparams, timeout5).json() if openid not in resp: return Response({code: 400, msg: 微信登录失败: %s % resp.get(errmsg)}, status400) openid resp[openid] user, _ UserProfile.objects.get_or_create(openidopenid) payload { user_id: user.id, openid: openid, exp: int(time.time()) 7 * 24 * 3600, } token jwt.encode(payload, settings.SECRET_KEY, algorithmHS256) return Response({code: 0, token: token, user_id: user.id})code2session 接口固定在 api.weixin.qq.com三个参数中 appid 和 secret 会暴露给后端不要写进小程序前端代码。请求失败时 resp 里会带 errcode 和 errmsg常见的是 40029code 无效和 40163code 已使用原因是同一个 code 只能换一次 openid调试时重复请求同一个 code 就会报错。JWT 的 exp 设成七天小程序的 token 过期后自动重新登录即可。3.5 分页、图片上传与查询参数接口细节的默认值列表接口在数据量小的时候看不出问题一旦导入几百条测试数据没有分页会让小程序端卡顿。在 settings.py 里配置全局分页REST_FRAMEWORK { DEFAULT_PAGINATION_CLASS: rest_framework.pagination.PageNumberPagination, PAGE_SIZE: 10, }这样小程序端请求 /api/recipes/?page1 会返回 count、next、previous、results 四个字段前端用结果中的 results 渲染列表。图片上传接口放在 Vue 管理后台这边用 DRF 的 APIView 接收文件class UploadImageView(APIView): def post(self, request): file request.FILES.get(file) if not file: return Response({code: 400, msg: 没有文件}) ext os.path.splitext(file.name)[-1].lower() filename str(int(time.time())) ext with open(os.path.join(settings.MEDIA_ROOT, filename), wb) as f: for chunk in file.chunks(): f.write(chunk) return Response({code: 0, url: settings.MEDIA_URL filename})文件名用时间戳重新生成避免中文名和重复名带来的一堆乱码问题。file.chunks() 是逐块读取适合图片文件。生产环境要考虑文件大小限制Django 默认没有限制你可以在 Nginx 层或者中间件里加。Vue 后台上传成功后拿到 URL把 URL 存到 recipe 表的 cover_image 字段。4. Vue 管理后台用 Element Plus 把菜品管理页面搭起来4.1 用 Vite 搭 Vue3 后台为什么不用 Vue2管理后台面向管理员功能是菜品的增删改查、分类管理、用户列表、数据统计。前端框架直接选 Vue 3 Vite Element Plus理由很简单Vite 冷启动和热更新比 Vue CLI 快一个量级后台开发中来回改表格和表单的体验差距非常大。npm create vitelatest familychef_admin -- --template vue cd familychef_admin npm install npm install element-plus axios vue-router安装完成后在 main.js 里全局注册 Element Plus。Vue2 的项目不建议选了Element UI 已经停止维护新写的毕设用 Vue3 生态更合理论文里写“基于 Vue3 的响应式数据绑定和组合式 API”也比旧版本有话说。4.2 axios 封装与路由跳转统一处理 401 和权限后台的请求都要带管理员 token而且登录过期时要跳回登录页。axios 封装成独立模块拦截器统一处理这些逻辑// src/api/index.js import axios from axios import router from ../router const request axios.create({ baseURL: /api, timeout: 15000, }) request.interceptors.request.use(config { const token localStorage.getItem(admin_token) if (token) { config.headers.Authorization Bearer token } return config }) request.interceptors.response.use( response response.data, error { if (error.response error.response.status 401) { localStorage.removeItem(admin_token) router.push(/login) } return Promise.reject(error) } ) export default requestbaseURL 用 /api 而不是 http://127.0.0.1:8000是为了配合 Vite 代理。后端所有接口前缀统一是 /api前端请求路径写 /api/recipes/代理会把请求转发到 Django 真实地址。401 拦截做的是统一跳登录这样任何接口报未授权都会回到登录页不用在每个页面里重复写判断。路由跳转用 vue-router登录页和主布局分开主布局里用 meta 字段控制哪些页面需要管理员权限。4.3 菜品管理页表格、弹窗、上传三件套菜品管理页是后台最核心的页面结构是顶部搜索栏中间 el-table 展示菜品列表按钮触发 el-dialog 弹窗新增或编辑弹窗里放 el-form 表单和 el-upload 图片上传。核心模板简化如下template div el-button typeprimary clickopenDialog()新增菜品/el-button el-table :datarecipeList border stripe el-table-column propid labelID width80 / el-table-column propname label菜名 / el-table-column propcategory_name label分类 / el-table-column label封面图 template #default{ row } el-image :srcrow.cover_image stylewidth: 60px; height: 60px / /template /el-table-column el-table-column label操作 template #default{ row } el-button sizesmall clickopenDialog(row)编辑/el-button el-button sizesmall typedanger clickdeleteRecipe(row.id)删除/el-button /template /el-table-column /el-table el-dialog v-modeldialogVisible :titleform.id ? 编辑菜品 : 新增菜品 el-form :modelform label-width80px el-form-item label菜名 el-input v-modelform.name / /el-form-item el-form-item label分类 el-select v-modelform.category placeholder选择分类 el-option v-forc in categories :keyc.id :labelc.name :valuec.id / /el-select /el-form-item el-form-item label封面图 el-upload action/api/upload/image/ :headersuploadHeaders img v-ifform.cover_image :srcform.cover_image classcover / /el-upload /el-form-item /el-form template #footer el-button clickdialogVisible false取消/el-button el-button typeprimary clicksaveRecipe保存/el-button /template /el-dialog /div /templateel-upload 的 action 直接写 /api/upload/image/走的是代理不需要写本机 IP。uploadHeaders 要把 token 带上否则 Django 端区分不了上传者。编辑和新增共用一个 dialog通过 form.id 判断是 PUT 还是 POST 请求。保存成功后重新拉一次列表不要手动修改表格数据保证页面和数据库一致。4.4 vite 代理与跨域本地联调的最后一公里后台开发时页面跑在 5173 端口Django 跑在 8000 端口浏览器直接请求必然跨域。虽然第 3 章里配置了 CORS_ALLOW_ALL_ORIGINS前端还是建议走代理这样生产环境和开发环境前端代码不用改地址。在 vite.config.js 里配置import { defineConfig } from vite import vue from vitejs/plugin-vue export default defineConfig({ plugins: [vue()], server: { port: 5173, proxy: { /api: { target: http://127.0.0.1:8000, changeOrigin: true, }, /media: { target: http://127.0.0.1:8000, changeOrigin: true, }, }, }, })/api 和 /media 都要代理。前者转发接口请求后者让上传的图片在 el-image 里能正常显示。这里踩坑最多的就是只代理了 /api图片全挂在 /media 下结果页面裂图。changeOrigin 设为 true是因为目标服务器拿到请求头时看到的 Host 是 127.0.0.1:8000避免 Django 的 ALLOWED_HOSTS 校验拒绝请求。生产环境部署时Nginx 里做同样的 location /api 和 location /media 转发即可。5. 小程序端联调与避坑清单从 wx.request 到真机调试5.1 wx.request 封装把 Promise 和 token 管理一起解决微信小程序的 wx.request 默认是回调风格多个接口串行请求时代码很难看。封装成 Promise 风格同时把 token 注入和错误提示统一处理// utils/request.js const BASE_URL http://127.0.0.1:8000 function request(path, method GET, data {}) { return new Promise((resolve, reject) { const token wx.getStorageSync(token) wx.request({ url: BASE_URL path, method: method, data: data, header: { Content-Type: application/json, Authorization: token ? Bearer token : , }, success(res) { if (res.statusCode 200 res.data.code 0) { resolve(res.data) } else if (res.statusCode 401) { wx.removeStorageSync(token) wx.navigateTo({ url: /pages/login/login }) } else { wx.showToast({ title: res.data.msg || 请求失败, icon: none }) reject(res.data) } }, fail(err) { wx.showToast({ title: 网络异常, icon: none }) reject(err) }, }) }) } module.exports { request }BASE_URL 在开发阶段直接用 127.0.0.1:8000手机真机调试时要把这个地址改成电脑在局域网内的 IP否则手机连不上。这里有个常见的翻车点微信开发者工具里勾选了“不校验合法域名”后请求能通真机预览时必须在小程序后台配置 request 合法域名域名必须备案并且是 HTTPS。没有正式域名时可以用开发者工具的“真机调试”功能临时绕过但给评委演示时还是建议用工具模拟器。5.2 首页与分类页setData 的最佳实践首页布局一般是顶部分类导航下面菜品瀑布流。页面加载时并发请求分类列表和推荐菜品数据回填用 setData// pages/index/index.js const { request } require(../../utils/request.js) Page({ data: { categories: [], recipes: [], activeCategory: 0, page: 1, hasMore: true, }, onLoad() { this.loadCategories() this.loadRecipes() }, async loadCategories() { const res await request(/api/categories/) this.setData({ categories: res.results }) }, async loadRecipes() { const category this.data.activeCategory const url category ? /api/recipes/?category category : /api/recipes/ const res await request(url) this.setData({ recipes: res.results }) }, onCategoryTap(e) { const id e.currentTarget.dataset.id this.setData({ activeCategory: id, page: 1 }, () { this.loadRecipes() }) }, })setData 的第二个参数是回调函数在数据更新完成后执行。分类切换时先把 activeCategory 和 page 重置再加载菜品列表避免旧列表残留。小程序端 setData 有性能问题一次性传入大数组会明显卡顿。接口做了分页后每次只传一页数据页面往下滚动时再加载下一页。图上不到 30 张菜品图时基本流畅。5.3 避坑清单真机图片不显示、中文乱码、401、CORS、版本不一致现象一开发者工具里图片正常真机上全部裂图。原因图片地址是 http://127.0.0.1:8000/media/xxx.jpg真机访问这个地址指向的是手机自己不是电脑。解决把 BASE_URL 和图片 URL 前缀都改成电脑局域网 IP并且让 Django 的 ALLOWED_HOSTS 加上这个 IP。现象二Django 接口返回的中文变成一串问号。原因MySQL 连接没指定 utf8mb4或者数据库表本身就是 latin1。解决先看数据库 SHOW VARIABLES LIKE character_set_server;确认是 utf8mb4再把 Django settings 里 DATABASES 的 OPTIONS 加上 charset改完重启 Django。现象三小程序登录后第一次请求成功过一会儿全部返回 401。原因JWT 过期或者 token 没带在 Header 里。解决检查 request.js 里 Authorization 的拼写Bearer 后面有空格检查登录接口返回的 token 是否真的存进了 Storage如果是在调试把 JWT 的 exp 调到 30 天省得反复登录。现象四Vue 后台请求 Django 报 CORS 错误network 面板显示 OPTIONS 请求 500。原因Django 的 CORS 配置放在中间件最后或者请求头里带了自定义字段但没有允许。解决corsheaders.middleware.CorsMiddleware 必须放在 CommonMiddleware 前面后端设置了 ALLOWED_HEADERS 的把 Authorization 加进去。现象五按视频教程操作却一直报错命令找不到包。原因教程录制时的 Python 版本和依赖版本和你本机不一致。解决先看 requirements.txt 有没有版本号有就严格按着装没有的话Python 优先用 3.8 到 3.10Node 用 16 以上Django 用 3.2 或 4.x 都行但不要把 Django 5 和一个老项目硬凑。提示微信开发者工具右上角的“详情 → 本地设置”里有“不校验合法域名”选项开发阶段必须勾上。真机预览时如果请求失败点开调试器的 Network 面板看具体报错比盲猜快得多。6. 优化与验收让这套毕业设计在答辩时站得住答辩演示最怕的是现场接口超时或者图片加载不出来。我习惯在答辩前做一次完整的验收清空数据库重新导入 database.sql启动 Django 和 Vue小程序重新编译按“首页 → 分类 → 详情 → 收藏 → 管理后台新增菜品 → 小程序刷新看到新菜”的路径走一遍。这个流程走通系统的主链路就没有问题了。给接口做一次简单的压测确认系统能扛住并发访问也是论文里可以写的亮点。用系统自带的 ab 命令ab -n 500 -c 50 http://127.0.0.1:8000/api/recipes/-n 500 表示总共 500 个请求-c 50 表示 50 个并发。跑完后看 Requests per second 和 Failed requests 两项。能跑到每秒几十个请求就足够应付毕设场景了。如果压测时失败率很高先看 MySQL 的最大连接数再看 Django 是不是 DEBUGTrue。DEBUG 模式会吞掉错误并拖慢请求部署或压测前务必关掉。日志是排查线上问题的最后一块拼图。Django 默认只在控制台打日志文件日志要自己配。在 settings.py 里加一个 FileHandler把 ERROR 级别以上的日志写到文件答辩演示时出了问题可以直接翻日志定位比在黑匣子里猜快得多。我自己的习惯是把日志文件和 media 目录都放在项目根目录外避免源码包和生成文件混在一起。这套技术栈的边界也值得说一句Vue 后台适合单管理员维护几百条菜品数据小程序端适合日活几千的量级。如果数据量到几十万条MySQL 加索引比换组件库更紧急如果要做实时推送Django 的 Websocket 是更能拉开差距的方向。这套题目我做过不止一次每次拿到新的源码包第一件事都是先跑数据库脚本再跑后端最后调前端。印象最深的一次就是忘配 MEDIA 路径Vue 里上传图片一直返回 404最后发现 urls.py 少了 static 路由。希望你这次少踩这些坑希望帮到你。本文还有配套的精品资源点击获取
02
RELATED NEWS

相关资讯

更多网站建设与数字化升级内容

03
WHY YAOTU

想打造同款高转化官网?

懂行业、懂生意,从建站到增长一站式陪跑

◈

场景化定制

不做模板站,围绕你的业务场景量身设计,小众不撞款。

◐

营销型架构

以转化目标组织内容与路径,让官网真正带来询盘。

▲

全周期服务

设计、开发、运营、运维一体,上线只是开始。

免费获取你的建站方案

留下需求,专属顾问 24 小时内为你输出方案建议。