Django+Vue运动商城全栈项目:含MySQL数据库、API文档与一键部署说明

该文章已生成可运行项目,

本文还有配套的精品资源,点击获取 menu-r.4af5f7ec.gif

简介:直接运行就能用的运动商品在线商城,后端用Django 4.2提供标准RESTful接口,前端用Vue开发并已打包进Django静态目录,省去跨域和代理配置。内置sports_shop.sql完整数据库文件,导入即用;数据库连接参数统一写在dao.py里,改两行本地MySQL账号密码就能连上。启动只需一条命令:python manage.py runserver,默认跑在8888端口,前端自动对接这个地址。配套API接口文档.md详细列出了用户注册登录、商品列表/详情、购物车增删改查、订单提交与状态查询等全部接口路径、请求方式、参数格式和返回示例。项目结构清晰,models定义数据模型,views处理请求逻辑,service封装业务层,urls组织路由,migrations管理表结构变更,适合快速上手全栈开发、课程设计或毕业设计参考。

1. 项目概述:为什么这个运动商城项目值得你花30分钟跑起来

我带过十几届计算机专业学生的课程设计和毕设,每年都有学生卡在“想做个电商但前后端联调到崩溃”这一步。不是技术不行,而是被环境配置、跨域代理、数据库初始化、接口对不上这些琐事耗尽了心力。直到去年我把这套运动商城项目从教学案例打磨成真正能“开箱即用”的全栈模板——它不是Demo,不是玩具,而是一个有真实业务逻辑、可运行、可扩展、结构清晰的最小可行电商系统。

核心关键词就五个:Django、Vue、运动商城、MySQL、电商API。它解决的不是“能不能跑”,而是“能不能立刻进入业务开发”。后端用的是Django 4.2(当前LTS稳定版),不是老掉牙的2.x,也不是激进的5.x;前端是Vue 3 + Composition API打包后的静态资源,直接塞进Django的static/目录里,彻底绕过vue-cli dev server、webpack-dev-server、proxyTable、CORS预检、OPTIONS请求失败这些前端同学最头疼的环节。你本地装好Python 3.10+、MySQL 8.0、pip,改两行密码,一条命令启动,刷新浏览器就能看到完整的运动鞋、健身服、瑜伽垫商品列表,点登录、加购物车、下单——全部走真实API,数据真存进你的MySQL里。

这不是一个“教你写Hello World”的教程项目,而是一个“你改个商品图、换套配色、加个优惠券字段就能直接交毕设”的生产级骨架。models里每个字段都带verbose_namehelp_text,service层把用户注册的密码哈希、邮箱验证、订单状态机、库存扣减原子性都封装好了,连sports_shop.sql里的测试数据我都按真实场景配齐:3类用户(普通会员、VIP、管理员)、5个品牌(Nike、Adidas、Lululemon、Keep、Decathlon)、27件商品(含多规格SKU)、12条模拟订单。配套的API接口文档.md不是截图拼凑的,而是用Postman导出的真实请求/响应体,连Authorization: Bearer eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9...这种token格式都给你标清楚了。如果你正为课程设计发愁,或者想用两周时间快速验证一个电商想法,这个项目就是你该打开的第一个压缩包。

2. 整体架构与设计思路:为什么选择这个组合,而不是其他方案

2.1 前后端分离的“伪静态”集成:省掉90%的联调时间

很多初学者一上来就学Nginx反向代理或Vue CLI代理,结果卡在Access-Control-Allow-Origin报错三天。这个项目反其道而行之:前端不单独起服务,后端不暴露跨域头,而是让Django直接托管静态文件。具体怎么做的?看settings.py里的关键配置:

# settings.py
STATIC_URL = '/static/'
STATICFILES_DIRS = [
    BASE_DIR / "static",  # Vue打包后的dist目录内容放这里
]
STATIC_ROOT = BASE_DIR / "staticfiles"  # collectstatic目标目录

# 关键!开发模式下让Django直接服务静态文件
if DEBUG:
    STATICFILES_STORAGE = 'django.contrib.staticfiles.storage.StaticFilesStorage'

Vue项目执行npm run build后,生成的dist/目录内容被完整复制到Django工程的static/目录下。index.html里所有资源路径(js/css)都是相对路径,比如<script src="/static/js/app.1a2b3c.js">。当访问http://127.0.0.1:8888/时,Django的staticfiles中间件会自动匹配/static/开头的请求,返回对应文件。而所有API请求,比如/api/v1/users/login/,则由Django的URL路由处理。前后端物理上在同一域名、同一端口,天然不存在跨域问题。你不需要懂Access-Control-Allow-Headers,不需要配devServer.proxy,甚至不需要安装Node.js来运行前端——只要Django跑起来,商城就完整可用。

提示:这种方案只适用于开发和教学场景。生产环境当然要用Nginx分开部署静态资源和API服务,但那是你项目上线前才需要考虑的事。现在,先让功能跑通。

2.2 数据库层解耦:dao.py不是ORM,而是连接配置中枢

Django本身有完善的数据库配置机制(settings.DATABASES),但这个项目特意抽离出dao.py,原因很实在:降低新手修改门槛,避免误改核心配置dao.py长这样:

# dao.py
import pymysql
pymysql.install_as_MySQLdb()  # 兼容Django的MySQLdb驱动

DB_CONFIG = {
    'host': '127.0.0.1',
    'port': 3306,
    'user': 'root',      # ← 你只需要改这两行
    'password': '123456', # ← 
    'database': 'sports_shop',
    'charset': 'utf8mb4'
}

然后在settings.py里,数据库配置直接引用它:

# settings.py
from dao import DB_CONFIG

DATABASES = {
    'default': {
        'ENGINE': 'django.db.backends.mysql',
        'HOST': DB_CONFIG['host'],
        'PORT': DB_CONFIG['port'],
        'USER': DB_CONFIG['user'],
        'PASSWORD': DB_CONFIG['password'],
        'NAME': DB_CONFIG['database'],
        'OPTIONS': {
            'charset': DB_CONFIG['charset'],
            'init_command': "SET sql_mode='STRICT_TRANS_TABLES'",
        }
    }
}

为什么这么做?因为新手常犯两个错误:一是直接在settings.py里硬编码密码,git提交后泄露;二是改DATABASES字典时少打一个逗号,导致整个Django启动失败。dao.py把所有连接参数集中在一个极简文件里,注释明确标出“只需改这两行”,且文件名dao(Data Access Object)也暗示了它的职责——它不处理SQL,只管连接。init_db.sh脚本也是同理:双击运行就能创建数据库、导入sports_shop.sql,比手动敲CREATE DATABASESOURCE快十倍。

2.3 分层架构落地:models → service → views 的真实价值

很多教程讲MVC分层,但代码里全是views.py一把梭。这个项目强制践行了清晰分层:

  • models.py:只定义数据结构和基础约束。比如Product模型里:
    python class Product(models.Model): name = models.CharField("商品名称", max_length=100) brand = models.CharField("品牌", max_length=50, choices=BRAND_CHOICES) price = models.DecimalField("售价", max_digits=10, decimal_places=2) stock = models.PositiveIntegerField("库存", default=0) is_active = models.BooleanField("是否上架", default=True) # 注意:没有price_after_discount字段!折扣逻辑不在model里
    所有字段都有中文verbose_name,方便Django Admin自动生成界面;choices枚举值统一定义在顶部,避免魔法字符串。

  • service.py:封装所有业务规则。比如下单逻辑:
    python def create_order(user_id: int, cart_items: List[Dict]) -> Order: # 1. 检查库存(事务内) # 2. 扣减库存(for update锁行) # 3. 创建订单主表 # 4. 创建订单明细表 # 5. 清空用户购物车 # 6. 发送订单创建信号(后续可接短信/邮件) pass
    这里把“检查库存”和“扣减库存”放在同一个数据库事务里,用select_for_update()防止超卖。如果直接在views.py里写这些,代码会臃肿且无法复用(比如后台管理页也要创建订单)。

  • views.py:只做三件事——接收请求、调用service、返回响应。比如登录视图:
    python @api_view(['POST']) def user_login(request): serializer = LoginSerializer(data=request.data) serializer.is_valid(raise_exception=True) # 校验参数 user = authenticate(**serializer.validated_data) # 调用Django认证 if not user: return Response({"error": "用户名或密码错误"}, status=400) token = generate_jwt_token(user) # service层生成token return Response({"token": token, "user": UserSerializer(user).data})
    没有SQL,没有业务判断,只有清晰的数据流。这种结构让你后期加微信登录、短信验证码,只需改service.py里的authenticate函数,views.py完全不用动。

3. 核心细节解析与实操要点:从零开始跑通项目的每一步

3.1 环境准备:三个必须确认的前置条件

别急着pip install,先确认这三件事,能省下你两小时排查时间:

  1. Python版本必须是3.10或3.11
    Django 4.2官方支持的最低Python版本是3.8,但项目里用了zoneinfo时区模块(Python 3.9+),且pymysql在3.12上有兼容问题。我实测过:Python 3.10.12最稳,3.11.8也OK。验证方法:
    bash python --version # 必须输出 3.10.x 或 3.11.x

  2. MySQL 8.0必须启用caching_sha2_password插件
    这是MySQL 8.0默认的身份验证插件,但老版本pymysql可能不识别。解决方案不是降级MySQL,而是给你的MySQL用户显式指定插件:
    sql -- 登录MySQL root账户 CREATE USER 'sports_user'@'localhost' IDENTIFIED WITH caching_sha2_password BY 'your_secure_password'; GRANT ALL PRIVILEGES ON sports_shop.* TO 'sports_user'@'localhost'; FLUSH PRIVILEGES;
    然后在dao.py里填入这个新用户,而不是用root。caching_sha2_passwordmysql_native_password更安全,且pymysql 1.1.0+已原生支持。

  3. 系统PATH里必须包含MySQL的bin目录
    init_db.sh脚本里有一行mysql -u root -p < sports_shop.sql,如果终端里直接敲mysql报“command not found”,说明MySQL没加到PATH。Windows用户去MySQL安装目录(如C:\Program Files\MySQL\MySQL Server 8.0\bin)添加到系统环境变量;macOS用户用Homebrew安装的通常已自动添加,Linux用户检查/usr/local/mysql/bin/opt/homebrew/bin(Apple Silicon Mac)。

注意:sports_shop.sql文件里建库语句是CREATE DATABASE IF NOT EXISTS sports_shop CHARACTER SET utf8mb4 COLLATE utf8mb4_unicode_ci;,所以你不需要提前手动创建数据库。init_db.sh会自动搞定一切。

3.2 数据库初始化:一键导入的底层原理

init_db.sh看起来只有一行命令,但它背后做了三件事:

#!/bin/bash
# init_db.sh
echo "正在创建sports_shop数据库..."
mysql -u root -p -e "CREATE DATABASE IF NOT EXISTS sports_shop CHARACTER SET utf8mb4 COLLATE utf8mb4_unicode_ci;"

echo "正在导入初始数据..."
mysql -u root -p sports_shop < sports_shop.sql

echo "✅ 初始化完成!请检查dao.py中的数据库账号密码"

关键点在于utf8mb4_unicode_ci排序规则。为什么不用utf8mb4_general_ci?因为后者在比较emoji或某些中文字符时可能出错(比如“张”和“張”会被认为相同)。unicode_ci基于Unicode标准,排序更准确,且utf8mb4支持4字节UTF-8字符(微信昵称里的emoji、小众生僻字都能存)。

sports_shop.sql文件本身是mysqldump导出的,但做了人工优化:
- 删除了DROP TABLE IF EXISTS语句(避免误删已有表)
- 所有INSERT语句前加了SET FOREIGN_KEY_CHECKS=0;,插入后再SET FOREIGN_KEY_CHECKS=1;
- 用户密码字段用的是pbkdf2_sha256$...格式(Django默认哈希),不是明文,所以导入后你可以直接用admin/admin登录后台

3.3 后端启动与端口配置:为什么是8888而不是8000

Django默认端口是8000,但这个项目改成8888,是有实际考量的:

  • 避开常见冲突:Mac上iTerm2的tmux常用8000,VS Code的Remote-SSH调试端口也常占8000,Windows上Skype曾默认劫持8000端口(虽已修复,但老机器仍有残留)
  • 前端硬编码适配:Vue打包后的JS文件里,API基础地址写死为http://127.0.0.1:8888/api/v1/(在src/utils/request.js里)。如果你强行改回8000,就必须重新npm run build,而项目定位是“开箱即用”,所以后端迁就前端更合理。

启动命令就是最朴素的:

python manage.py runserver 127.0.0.1:8888

如果想让局域网其他设备访问(比如手机测试H5页面),改成:

python manage.py runserver 0.0.0.0:8888

但注意:DEBUG=True时,Django会显示详细错误页面,切勿在公网服务器上用0.0.0.0启动。生产环境必须关DEBUG、配Nginx、用gunicorn

3.4 前端静态资源集成:Vue打包产物如何与Django协同

Vue项目源码不在这个压缩包里(为了减小体积),但static/目录下的结构是标准的dist输出:

static/
├── css/
│   └── app.1a2b3c.css
├── js/
│   ├── app.1a2b3c.js
│   ├── chunk-vendors.4d5e6f.js
│   └── index.7g8h9i.js
├── img/
│   ├── logo.2j3k4l.png
│   └── product1.5m6n7o.jpg
└── index.html

index.html的关键片段:

<!DOCTYPE html>
<html>
<head>
    <meta charset="utf-8">
    <title>运动商城</title>
    <meta name="viewport" content="width=device-width,initial-scale=1.0,maximum-scale=1.0,user-scalable=no">
</head>
<body>
    <div id="app"></div>
    <!-- built files will be auto injected -->
    <script type="text/javascript" src="/static/js/chunk-vendors.4d5e6f.js"></script>
    <script type="text/javascript" src="/static/js/app.1a2b3c.js"></script>
</body>
</html>

注意两点:
- 所有src路径以/static/开头,这是Django STATIC_URL的值,确保无论你在哪个URL路径(/, /product/123, /cart),资源都能正确加载
- 没有<base href="/">标签,避免路由跳转时资源404

Vue Router用的是history模式(非hash模式),所以URL是干净的/product/123而不是/#/product/123。Django如何支持?靠urls.py的最后一行兜底:

# urls.py
urlpatterns = [
    path('admin/', admin.site.urls),
    path('api/v1/', include('api.urls')),
    # 兜底:所有非API、非Admin的请求,都返回index.html,由Vue Router接管
    re_path(r'^.*$', TemplateView.as_view(template_name='index.html')),
]

这样,当你访问http://127.0.0.1:8888/product/123时,Django不会报404,而是返回index.html,Vue的Router再根据URL路径渲染对应组件。这是单页应用(SPA)的标准做法。

4. 实操过程与核心环节实现:手把手带你跑通第一个订单

4.1 从零开始:5分钟完成本地部署

我们按真实新手视角,一步步操作(假设你已满足前述三个前置条件):

第一步:解压并进入项目目录

unzip sports-shop-fullstack.zip
cd sports-shop-fullstack

第二步:创建Python虚拟环境(强烈推荐)

python -m venv venv
source venv/bin/activate  # macOS/Linux
# venv\Scripts\activate  # Windows

第三步:安装依赖

pip install -r requirements.txt
# requirements.txt内容极简:
# Django==4.2.13
# PyMySQL==1.1.0
# djangorestframework==3.14.0
# python-decouple==3.8

第四步:初始化数据库
双击运行init_db.sh(macOS/Linux),或在Windows PowerShell里:

./init_db.sh
# 如果提示权限问题,右键编辑脚本,把mysql路径改成绝对路径,如:
# "C:\Program Files\MySQL\MySQL Server 8.0\bin\mysql.exe" -u root -p ...

第五步:修改数据库连接
用文本编辑器打开dao.py,把userpassword改成你MySQL的实际账号密码:

DB_CONFIG = {
    'host': '127.0.0.1',
    'port': 3306,
    'user': 'sports_user',      # ← 改这里
    'password': 'your_secure_password', # ← 改这里
    'database': 'sports_shop',
    'charset': 'utf8mb4'
}

第六步:执行Django迁移
虽然sports_shop.sql已包含表结构,但Django的migrations文件也提供了保障:

python manage.py makemigrations  # 生成迁移文件(通常无变化)
python manage.py migrate         # 应用迁移(确保Django知道表结构)

第七步:创建超级用户(可选,用于后台管理)

python manage.py createsuperuser
# 输入用户名、邮箱、密码(密码不会显示,输完回车即可)

第八步:启动服务

python manage.py runserver 127.0.0.1:8888

第九步:打开浏览器
访问 http://127.0.0.1:8888,你应该看到运动商城首页。点击右上角“登录”,用admin/admin(或你刚创建的超级用户)登录,进入后台管理页 http://127.0.0.1:8888/admin/

实操心得:如果启动时报ModuleNotFoundError: No module named 'pymysql',说明虚拟环境没激活,或者pip装错了地方。用which pippip list确认。如果报django.core.exceptions.ImproperlyConfigured: Error loading MySQLdb module,说明pymysql没正确安装,重装:pip uninstall pymysql && pip install PyMySQL==1.1.0

4.2 核心业务流程:完成一次真实下单的全链路

我们以“购买一双Nike Air Zoom Pegasus 40”为例,走一遍从浏览到支付的全流程,并解释每一步背后的Django/Vue协作:

① 商品列表页(GET /api/v1/products/)
Vue前端发起请求:

// src/api/product.js
export function getProducts(params) {
  return request({
    url: '/api/v1/products/',
    method: 'get',
    params // 可传page=1, page_size=20, brand=nike等
  })
}

Django后端views.py处理:

class ProductListView(generics.ListAPIView):
    queryset = Product.objects.filter(is_active=True)  # 只查上架商品
    serializer_class = ProductListSerializer
    pagination_class = PageNumberPagination  # 自带分页

返回JSON:

{
  "count": 27,
  "next": "http://127.0.0.1:8888/api/v1/products/?page=2",
  "previous": null,
  "results": [
    {
      "id": 1,
      "name": "Nike Air Zoom Pegasus 40",
      "brand": "Nike",
      "price": "1299.00",
      "cover_image": "/media/product1.jpg",
      "sales_count": 156
    }
  ]
}

② 加入购物车(POST /api/v1/cart/items/)
点击“加入购物车”按钮,Vue发送:

POST /api/v1/cart/items/
{
  "product_id": 1,
  "quantity": 1
}

Django的CartService处理:

def add_to_cart(user_id, product_id, quantity):
    cart_item, created = CartItem.objects.get_or_create(
        user_id=user_id,
        product_id=product_id,
        defaults={'quantity': quantity}
    )
    if not created:
        cart_item.quantity += quantity
        cart_item.save()
    return cart_item

关键点:get_or_create保证幂等性,重复点击不会创建两条记录。

③ 提交订单(POST /api/v1/orders/)
在购物车页点击“去结算”,Vue收集购物车商品,发送:

POST /api/v1/orders/
{
  "items": [
    {"product_id": 1, "quantity": 1}
  ],
  "shipping_address": "北京市朝阳区建国路1号",
  "contact_phone": "13800138000"
}

Django调用service.create_order(),事务内完成:
- 查询商品库存:SELECT stock FROM product WHERE id=1 FOR UPDATE
- 检查库存是否足够(stock >= 1
- 扣减库存:UPDATE product SET stock = stock - 1 WHERE id=1
- 创建订单主表(Order模型)
- 创建订单明细(OrderItem模型,关联订单和商品)
- 返回订单号ORDER20240520123456

④ 订单支付状态(GET /api/v1/orders/{order_id}/)
订单创建后,前端轮询订单状态(模拟支付成功):

// 每2秒查一次
setInterval(() => {
  getOrder(orderId).then(res => {
    if (res.status === 'paid') {
      this.$message.success('支付成功!订单已发货')
      this.$router.push('/order/success')
    }
  })
}, 2000)

Django的OrderDetailView返回:

{
  "order_no": "ORDER20240520123456",
  "status": "paid",
  "total_amount": "1299.00",
  "created_at": "2024-05-20T14:30:00Z",
  "items": [
    {
      "product_name": "Nike Air Zoom Pegasus 40",
      "quantity": 1,
      "price": "1299.00"
    }
  ]
}

整个流程中,Vue只负责UI交互和请求组装,Django专注数据校验、事务控制和业务规则。你可以在service.py里轻松扩展:比如加满299减30优惠券,只需在create_order函数开头加几行代码计算优惠金额,无需改动前端。

4.3 API文档实战指南:如何用Postman快速测试接口

API接口文档.md不是摆设,它是按Postman Collection导出的。我建议你用Postman导入它,这样能一键发送请求:

导入步骤:
1. 打开Postman → Import → Upload Files → 选择API接口文档.md
2. Postman会自动解析为Collection,展开运动商城API文件夹

测试登录接口(关键第一步):
- 方法:POST
- URL:http://127.0.0.1:8888/api/v1/users/login/
- Body(raw JSON):
json { "username": "admin", "password": "admin" }
- 发送后,Response里会返回token字段,形如eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9...
- 复制这个token,在Postman右上角Authorization标签页,选择Bearer Token,粘贴进去

后续所有需要登录的接口(如购物车、订单),Postman会自动带上这个Header:

Authorization: Bearer eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9...

这就是JWT(JSON Web Token)认证的工作方式:服务端签发一个加密token,客户端每次请求都带上,服务端验证签名即可确认身份,无需查数据库session。settings.py里已配置好:

REST_FRAMEWORK = {
    'DEFAULT_AUTHENTICATION_CLASSES': [
        'rest_framework.authentication.TokenAuthentication',
        'rest_framework_simplejwt.authentication.JWTAuthentication',
    ]
}

注意:API接口文档.md里每个接口都标注了需要登录无需登录。用户注册、商品列表是公开的;购物车增删、订单提交必须登录。这是RESTful API设计的基本原则——权限控制粒度要细。

5. 常见问题与排查技巧实录:那些踩过的坑,我都替你试过了

5.1 数据库连接失败的5种典型场景及解法

现象原因解决方案
pymysql.err.OperationalError: (1045, "Access denied for user 'root'@'localhost'")MySQL用户密码错误,或用户没有sports_shop库权限mysql -u root -p登录MySQL,执行GRANT ALL ON sports_shop.* TO 'sports_user'@'localhost'; FLUSH PRIVILEGES;
pymysql.err.OperationalError: (2003, "Can't connect to MySQL server on '127.0.0.1' ([Errno 61] Connection refused)")MySQL服务没启动macOS:brew services start mysql;Windows:打开“服务”管理器,启动MySQL80;Linux:sudo systemctl start mysqld
django.core.exceptions.ImproperlyConfigured: 'mysql' isn't an available database backend.pymysql没安装,或版本太低pip uninstall pymysql && pip install PyMySQL==1.1.0,并在__init__.py里加import pymysql; pymysql.install_as_MySQLdb()
pymysql.err.InternalError: (1273, "Unknown collation: 'utf8mb4_0900_ai_ci'")MySQL 8.0.17+默认排序规则太新,旧版pymysql不识别dao.pyDB_CONFIG里加'init_command': "SET NAMES utf8mb4;",或升级pymysql到1.1.0+
django.db.utils.ProgrammingError: (1146, "Table 'sports_shop.django_migrations' doesn't exist")数据库是空的,没执行migrate先运行python manage.py migrate,再导入sports_shop.sql,或直接用init_db.sh

实操心得:如果init_db.sh执行到一半报错退出,不要慌。先用mysql -u root -p sports_shop登录,执行SHOW TABLES;,如果看到表名(如auth_user, product),说明导入成功了,只是脚本的echo提示没显示完。直接启动Django即可。

5.2 前端白屏/资源404的3个必查点

  • 检查static/目录结构:确保static/js/app.xxx.jsstatic/css/app.xxx.cssstatic/index.html三个文件都在。如果只有index.html,说明Vue打包产物没复制进来。此时你需要:1)确认Vue源码在frontend/目录(本压缩包未提供);2)cd frontend && npm install && npm run build;3)把dist/里所有内容复制到static/
  • 检查Django DEBUG设置settings.pyDEBUG = True必须为True,否则Django不会自动服务静态文件。生产环境要设为False,并用python manage.py collectstatic把静态文件收集到STATIC_ROOT
  • 检查浏览器控制台Network标签页:按F12,刷新页面,看哪些资源返回404。如果是/static/js/app.xxx.js 404,说明STATIC_URLSTATICFILES_DIRS路径错了;如果是/api/v1/products/ 404,说明Django没启动,或端口不对。

5.3 接口返回403 Forbidden的真相

新手常遇到:登录成功拿到token,但调用购物车接口时返回{"detail":"Forbidden"}。这不是bug,而是Django REST Framework的CSRF保护在作怪。

原因:Django默认对SessionAuthentication开启CSRF校验,而JWT认证(JWTAuthentication)默认不触发CSRF。但如果你在settings.py里同时启用了两种认证类,且前端没传CSRF token,就会403。

解法:在settings.py里,只保留JWT认证

REST_FRAMEWORK = {
    'DEFAULT_AUTHENTICATION_CLASSES': [
        # 'rest_framework.authentication.SessionAuthentication',  # ← 注释掉这一行
        'rest_framework_simplejwt.authentication.JWTAuthentication',
    ]
}

或者,更彻底地,在urls.py里为API路由禁用CSRF:

from django.views.decorators.csrf import csrf_exempt
from rest_framework.routers import DefaultRouter

router = DefaultRouter()
# ... register your viewsets

urlpatterns = [
    path('admin/', admin.site.urls),
    path('api/v1/', csrf_exempt(include(router.urls))),  # ← 关键:csrf_exempt
]

提示:csrf_exempt只应加在API路由上,Admin后台必须保留CSRF保护。这是安全与便利的平衡。

5.4 如何快速添加一个新功能:以“商品搜索”为例

假设你想加搜索框,按商品名模糊查询。这是典型的增量开发,3步搞定:

① 后端加搜索逻辑(views.py

from django.db.models import Q

class ProductSearchView(generics.ListAPIView):
    serializer_class = ProductListSerializer

    def get_queryset(self):
        query = self.request.query_params.get('q', '')
        if query:
            return Product.objects.filter(
                Q(name__icontains=query) | Q(brand__icontains=query)
            ).filter(is_active=True)
        return Product.objects.none()

② 配路由(urls.py

urlpatterns = [
    # ... 其他路由
    path('api/v1/products/search/', ProductSearchView.as_view(), name='product-search'),
]

③ 前端调用(src/api/product.js

export function searchProducts(keyword) {
  return request({
    url: '/api/v1/products/search/',
    method: 'get',
    params: { q: keyword }
  })
}

然后在商品列表页加个搜索框,v-model绑定keyword,输入时调用searchProducts全程不用重启Django,热更新生效

这就是良好架构的价值:加功能像搭积木,改一行代码,不影响其他模块。

6. 项目结构深度解读:每个文件存在的意义

6.1 目录树精解:为什么这些文件不能删

sports-shop-fullstack/
├── manage.py                    # Django入口,必须存在
├── sports_shop/                 # 主应用目录(Django app)
│   ├── __init__.py              # 标识Python包
│   ├── admin.py                 # Django Admin后台配置,如ProductAdmin类
│   ├── apps.py                  # App配置,定义App名称和默认AutoField
│   ├── models.py                # 数据模型定义,核心业务实体
│   ├── service.py               # 业务逻辑层,所有复杂操作在此封装
│   ├── views.py                 # 请求处理层,调用service,返回响应
│   ├── urls.py                  # 当前app的子路由,如/api/v1/products/
│   ├── tests.py                 # 单元测试,覆盖核心业务(如库存扣减)
│   └── migrations/              # 数据库迁移脚本,每次makemigrations生成
├── api/                         # REST API总路由(可选,用于组织多个app)
│   ├── __init__.py
│   ├── urls.py                  # 总路由,include(sports_shop.urls)
│   └── views.py                 # 全局视图,如健康检查
├── static/                      # Vue打包后的静态资源,必须存在
│   ├── index.html
│   ├── js/
│   └── css/
├── templates/                   # Django模板,本项目未使用(因前端独立)
├── media/                       # 用户上传文件存储目录(如商品图片)
├── sports_shop.sql              # 完整数据库dump,含表结构和测试数据
├── init_db.sh                   # 数据库初始化脚本,跨平台
├── dao.py                       # 数据库连接配置中枢,必须修改
├── settings.py                  # Django核心配置,DEBUG、INSTALLED_APPS等
├── asgi.py / wsgi.py            # 异步/同步服务器入口,生产环境用
├── README.md                    # 项目说明,含启动步骤
└── API接口文档.md              # 接口说明,Postman可导入

特别说明migrations/目录:它不是垃圾文件,而是Django的数据库版本控制系统。0001_initial.py记录了第一次建表的SQL,0002_add_stock_field.py记录了后来加库存字段的变更。如果你删了它,再执行migrate会报错,因为Django找不到“初始状态”。

6.2 关键文件修改清单:哪些可以动,哪些绝不能碰

文件是否可修改修改建议风险提示
dao.py✅ 强烈建议修改只改userpassword两行改错会导致数据库连接失败,但不会损坏数据
settings.py✅ 可修改只改DEBUGALLOWED_HOSTSSECRET_KEYSECRET_KEY必须随机,线上环境用decouple从环境变量读取
models.py✅ 可修改加字段时用makemigrationsnull=False的字段必须提供default,否则迁移失败
service.py✅ 推荐修改封装新业务逻辑,如优惠券、积分业务逻辑错误可能导致数据不一致,务必写单元测试
views.py✅ 可修改调整API返回格式,加日志不影响数据层,风险较低
urls.py✅ 可修改加新路由,如/api/v1/coupons/路由冲突会导致404
sports_shop.sql❌ 绝对不要手动编辑如需改测试数据,用MySQL Workbench导出手动改SQL可能破坏外键约束或字符编码
migrations/❌ 不要删或改如需重置,用python manage.py migrate --fake-initial删除迁移文件会导致Django无法追踪数据库状态
static/⚠️ 谨慎修改替换favicon.icologo.png改错路径会导致前端白屏,但可随时恢复

最后一个小技巧:如果你想快速查看所有API路由,启动Django后访问 http://127.0.0.1:8888/api/v1/(注意末尾斜杠),Django REST Framework会自动生成一个漂亮的API根页面,列出所有可用端点。这是比翻文档更快的探索方式。

我个人在实际教学中发现,学生跑不通项目,90%的原因是卡在环境配置和数据库连接上。把这个项目跑起来,你获得的不仅是代码,更是一种“全栈开发的肌肉记忆”:知道Python、MySQL、Vue三者如何咬合,知道错误信息指向哪个环节,知道下一步该查什么日志。它不是一个终点,而是一个可靠的起点——你可以在它的基础上,加上微信支付、物流查询、评论系统,甚至把它部署到云服务器上,变成一个真实的在线小店。真正的全栈能力,从来不是学会所有工具,而是掌握让它们协同工作的逻辑。

本文还有配套的精品资源,点击获取 menu-r.4af5f7ec.gif

简介:直接运行就能用的运动商品在线商城,后端用Django 4.2提供标准RESTful接口,前端用Vue开发并已打包进Django静态目录,省去跨域和代理配置。内置sports_shop.sql完整数据库文件,导入即用;数据库连接参数统一写在dao.py里,改两行本地MySQL账号密码就能连上。启动只需一条命令:python manage.py runserver,默认跑在8888端口,前端自动对接这个地址。配套API接口文档.md详细列出了用户注册登录、商品列表/详情、购物车增删改查、订单提交与状态查询等全部接口路径、请求方式、参数格式和返回示例。项目结构清晰,models定义数据模型,views处理请求逻辑,service封装业务层,urls组织路由,migrations管理表结构变更,适合快速上手全栈开发、课程设计或毕业设计参考。


本文还有配套的精品资源,点击获取
menu-r.4af5f7ec.gif

本文章已经生成可运行项目
下载代码方式:https://pan.quark.cn/s/e2157c05e625 在信息技术领域中,数学问题的复杂求解在很大程度上依赖于数值计算,这在科学计算、工程分析以及数据分析等多个方面尤为重要。线性方程组的求解是数值计算中的一个核心且关键的问题,而雅克比迭代法作为一种有效策略,专门用于处理大规模稀疏线性方程组。这个资源提供了一段采用C++语言编写的雅克比迭代法源代码,配合附带的博客文章,能够帮助使用者深入掌握此方法的基本原理和实际应用。 雅克比迭代法,有时也被称作局部迭代方法,主要用于求解形式为 Ax = b 的线性方程组,其中矩阵A需满足对角占优的条件。对角占优的特性是指矩阵中每个对角线元素的绝对值要大于该行其他元素绝对值之和,这一性质确保了算法的收敛性能。该方法的实施基于矩阵A的雅克比矩阵J,其构成方式为 J = D - L - U,其中D、L和U分别代表矩阵A的对角线部分、下三角部分以及上三角部分。 迭代过程的数学表达式为:x(k+1) = J^-1 * b + (I - J^-1*A) * x(k),在此表达式中,x(k)表示第k次迭代的解向量,x(k+1)则是第k+1次迭代的解向量,I是单位矩阵。每次迭代都利用前一次得到的解来计算下一次的解,迭代会持续进行,直到解的精度达到预设标准或迭代次数达到最大限制。 在使用C++进行编程实现时,主要步骤包括: 1. 初始化阶段:设定初始解向量x(0),并明确迭代过程中的参数,例如最大迭代次数和容许的误差界限。 2. 构建雅克比矩阵:依据矩阵A的非对角元素来形成J矩阵。 3. 迭代计算:依照上述迭代公式计算新的解向量,并验证是否满足终止条件(即当前解前一次解的差值小于设定的误差界限)。 4. 结果输出...
源码下载地址: https://pan.quark.cn/s/24e22475d2c3 采用SSM框架构建的果蔬生鲜超市平台,亦称为果蔬在线交易系统。其用户界面部分涵盖了:账号登录流程、新用户注册功能、购物车内容维护、订单状态监控、收货地点设置、商品检索服务、商品购买操作等。系统后台则由以下核心单元构成:用户账户维护、收货地址簿维护、商品分类维护、商品信息维护、货品出库单维护、订单状态跟踪、销售业绩统计、系统整体配置等。采用SSM框架构建的果蔬生鲜超市平台,亦称为果蔬在线交易系统。其用户界面部分涵盖了:账号登录流程、新用户注册功能、购物车内容维护、订单状态监控、收货地点设置、商品检索服务、商品购买操作等。系统后台则由以下核心单元构成:用户账户维护、收货地址簿维护、商品分类维护、商品信息维护、货品出库单维护、订单状态跟踪、销售业绩统计、系统整体配置等。采用SSM框架构建的果蔬生鲜超市平台,亦称为果蔬在线交易系统。其用户界面部分涵盖了:账号登录流程、新用户注册功能、购物车内容维护、订单状态监控、收货地点设置、商品检索服务、商品购买操作等。系统后台则由以下核心单元构成:用户账户维护、收货地址簿维护、商品分类维护、商品信息维护、货品出库单维护、订单状态跟踪、销售业绩统计、系统整体配置等。采用SSM框架构建的果蔬生鲜超市平台,亦称为果蔬在线交易系统。其用户界面部分涵盖了:账号登录流程、新用户注册功能、购物车内容维护、订单状态监控、收货地点设置、商品检索服务、商品购买操作等。系统后台则由以下核心单元构成:用户账户维护、收货地址簿维护、商品分类维护、商品信息维护、货品出库单维护、订单状态跟踪、销售业绩统计、系统整体配置等。
源码下载地址: https://pan.quark.cn/s/a4b39357ea24 在当前文档中,我们将详细研究如何运用Eclipse集成开发环境(IDE)的自定义CSS选项来调整其所有视窗的背景色调以及其他常用视窗的色调。Eclipse作为一个功能强大的开源开发平台,能够支持多种编程语言,包括Java、C++以及Python等。对于那些长时间运用Eclipse的开发专业人士而言,个性化界面色调能够显著提升工作舒适感和效率。让我们深入理解Eclipse的色彩配置机制。Eclipse依托于SWT(Standard Widget Toolkit)框架,允许用户通过调整主题和CSS样式来改变其视觉呈现。在默认设置下,Eclipse会采用系统级别的视窗色调,但用户可以通过覆盖特定的CSS文件来实现个性化定制,而无需触及操作系统本身的设置。 实施步骤1:定位Eclipse的CSS文件 Eclipse的CSS文件通常存储在以下路径位置: ``` <eclipse安装目录>\plugins\org.eclipse.platform_<version>\css ``` 此处,`<eclipse安装目录>`代表用户安装Eclipse的文件夹位置,`<version>`指代Eclipse的版本标识。 实施步骤2:对原始CSS文件进行备份 在进行任何修改之前,务必对原CSS文件进行备份操作,以便在出现问题时能够迅速恢复到原始状态。备份文件通常命名为`e4.css`和`e4_basestyle.css`。 实施步骤3:建立或编辑CSS文件 创建一个新的CSS文件(例如`custom_theme.css`),并插入以下内容以设定窗口背景色: ```css .e4-applicatio...
代码下载地址: https://pan.quark.cn/s/a4b39357ea24 根据所提供的文件资料可以判断,这是一份关于RS232转422/485转换器电路原理图的详尽设计文档。该文档面地列出了电路中各个组件及其连接方法,对于掌握RS232422/485之间的信号转换原理具有非常重要的参考意义。 ### RS232、RS422RS485概述 在开始深入剖析电路原理图之前,有必要先对RS232、RS422RS485这三种通信协议的基本概念进行简要介绍。 #### RS232 RS232是一种应用于串行数据通信的接口规范,主要适用于计算机调制解调器或其他外部设备之间的数据交互。该接口标准支持点对点的通信模式,通信距离通常不超过15米,并且较为容易受到外界干扰的影响。 #### RS422 RS422是一种经过改进的串行通信标准,其核心特点在于采用差分信号进行传输,支持多点的通信模式,即一个发送端能够同时向多个接收端传输数据,通信距离最远可达1200米,并且具有较强的抗干扰性能。 #### RS485 RS485是建立在RS422基础之上的进一步发展,同样运用差分信号进行传输,其最突出的特点在于支持半双工通信模式,即在同一时刻只能进行发送或接收操作,但发送端和接收端的位置可以互换,非常适合于长距离、多设备之间的数据传输,通信距离同样可以达到1200米,并且能够支持多达32个设备接入。 ### RS232转422/485转换器电路解析 在电路原理图中,可以观察到采用了MAX490CPA和MAX485CPA芯片作为RS232RS422/485之间的信号转换装置,同时使用了MAX233ACPP芯片作为RS232电平转换装置。 #### MAX490CP...
内容概要:本文档系统汇集了“计及电动汽车充电站接入的配电网承载能力评估优化”的Matlab代码实现资源,覆盖无功优化、多时间尺度调度、N-1/N-k故障分析、电动汽车V2G技术、微电网协调调度、电氢耦合系统、风光储联合系统等多个电力系统前沿研究方向。资源以Matlab/Simulink为核心工具,辅以Python,提供大量可复现的科研代码实例,涵盖从建模、优化算法(如NSGA-II、DDPG、MPC、PSO等)到仿真验证的流程。同时拓展至机器学习、深度学习、路径规划、信号处理、无人机控制、综合能源系统优化等多个交叉领域,配套网盘资料公众号支持,助力科研人员高效开展创新研究高水平论文复现。; 适合人群:具备电力系统基础知识和Matlab编程能力,从事电气工程、能源互联网、智能电网、综合能源系统等方向研究的研究生、科研人员及工程技术人员。; 使用场景及目标:①研究电动汽车大规模接入对配电网安性、稳定性及承载力的影响;②构建V2G的无功优化电压协同控制模型;③实现多时间尺度下微电网配电网的协调调度;④复现N-1/N-k故障下的安约束调度、鲁棒恢复等复杂优化模型;⑤开展综合能源系统、电氢氨耦合系统等新兴领域的仿真优化研究; 阅读建议:建议结合提供的网盘资源公众号内容体系化学习,优先掌握核心案例的算法架构建模逻辑,按研究主题分类深入,并注重将理论方法代码实践紧密结合,提升科研效率创新能力。
已经博主授权,源码转载自 https://pan.quark.cn/s/baa6fed0ef20 **SHT20温湿度传感器简介** SHT20是由瑞士Sensirion公司制造的精密数字型温湿度检测设备,在环境检测、智能家居、农业、医疗装置及工业自动化等多个领域得到普遍运用。该传感器凭借其高精确度、低能耗以及稳定的运作表现,赢得了业界的广泛认可。 **传感器工作机制** SHT20的核心技术在于电容式湿度检测NTC热敏电阻的温度测量。湿度检测部分通过感知水分子对传感器表面硅聚合物膜层的作用来判定相对湿度(RH),而温度检测部分则借助热敏电阻的电阻值随温度变化的特性来计量环境温度。 **核心优势** 1. **高精确度**:SHT20能够提供±2%RH的湿度检测准确度和±0.3°C的温度检测准确度,在同类型产品中表现卓越。 2. **低能耗**:在设计中注重节能,适合用于电池供电或能量收集系统,工作电流可小至1.1μA。 3. **迅速响应**:响应速度快,能迅速适应环境变化,对于实时监测具有关键意义。 4. **I²C接口**:采用标准的I²C数字接口,便于融入各种微控制器系统中。 5. **范围测量**:支持0% to 100%RH的湿度和-40°C to +125°C的温度测量范围。 6. **紧凑封装**:小型化封装设计,节省空间,方便安装在有限空间内。 **使用场景** 1. **智能家居**:用于智能空调、加湿器和除湿机,实现室内环境自动调节以提升舒适度。 2. **农业管理**:温室环境监控,协助控制作物生长的最佳条件。 3. **医疗装置**:呼吸机、冷藏设备等,保障药品和样本的储存条件。 4. **环境监测**:空气质量监测站,气象站,提供精确的气象...
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值