本讲是M0里程碑的收官 。第4讲前端能跑,第5讲后端能跑,下一讲开始就是「业务代码」了。
⚠️ M0成就解锁 :跑通
python manage.py runserver,浏览器访问/api/v1/health/返回{"status": "ok"}。建议先 点赞 + 收藏 + 关注,配 settings 分层时随时回查。
一、为什么用Django而不是Flask
很多新人会问:
现在不都用FastAPI了吗?Django不老吗?
这个问题有四层回答。
第一层:教学曲线。
Django是「全家桶」------ORM、Admin、Auth、迁移、缓存、信号、中间件、国际化开箱即用。Flask 灵活但散装,你每做一个新模块都要选「这个项目目录该长什么样、这个ORM怎么用、这个Admin怎么搭」。
专栏如果用Flask,就会陷入选型疲劳。Django把这些决策提前做了,你只需要跟着学。
第二层:就业面。
打开招聘软件搜「Python后端」,Django出现频次远高于FastAPI。FastAPI是新趋势没错,但国内大部分存量系统是Django。学完能直接对接企业真实项目。
第三层:生态完整度。
Django的第三方包覆盖了你能想到的所有场景:
- DRF(API)
- SimpleJWT(鉴权)
- Celery(异步)
- channels(WebSocket)
- Debug Toolbar(调试)
- Django Admin(后台)
- django-cors-headers(CORS)
FastAPI生态也在长,但很多场景需要自己拼。
第四层:性能不是短板。
Django引入ASGI异步视图 + async ORM,在I/O密集场景与FastAPI持平。后面我们会用Celery把CPU密集任务扔出主线程。
💡 什么时候选FastAPI ?
纯异步 + 高并发 + 微服务场景(比如物联网网关、实时数据流),FastAPI更合适。本专栏是电商B2C单体应用,Django更匹配。
二、创建工程
切到对应的特性分支:
bash
cd ~/workspace/shopx
git switch develop
git pull
git switch -c feature/lecture-005-backend-scaffold
创建 Django 工程
在项目根目录创建backend/子目录作为后端代码根:
bash
mkdir backend
cd backend
激活虚拟环境(第 2 讲建的):
bash
source ../.venv/bin/activate
# Windows WSL: 同样命令
# 注意路径是 ../.venv 因为我们在 backend 子目录
💡 也可以把
.venv/放在backend/内部,路径更短。但本专栏用monorepo,.venv/放根目录统一管理。
创建 Django 工程:
bash
django-admin startproject shopx .
末尾的
.很重要 ------它表示在当前目录(backend/)创建工程,而不是再嵌套一层shopx/shopx/。如果你忘了打点,后面路径会很乱。
生成的目录:
text
backend/
├── manage.py # 命令行入口
└── shopx/
├── __init__.py
├── asgi.py # ASGI 入口(异步)
├── wsgi.py # WSGI 入口(同步)
├── settings.py # 配置文件(本讲要拆)
└── urls.py # 根路由
验证Django装好
bash
python manage.py runserver
# Watching for file changes with StatReloader
# Starting development server at http://127.0.0.1:8000/
# Quit the server with CONTROL-C.
浏览器访问http://127.0.0.1:8000/,看到Django默认欢迎页(火箭图)。Ctrl+C关掉,我们继续改配置。
三、第一个App:health
Django的「App」是一个可独立复用的功能模块。商城后端最终会有11个app(users goods cart orders ...),但本讲只建一个最简的 health------用于探活接口。
创建health app
bash
python manage.py startapp health
生成:
text
health/
├── __init__.py
├── admin.py
├── apps.py
├── migrations/
│ └── __init__.py
├── models.py
├── tests.py
└── views.py
注册到INSTALLED_APPS
打开shopx/settings.py,找到INSTALLED_APPS,加上:
python
INSTALLED_APPS = [
'django.contrib.admin',
'django.contrib.auth',
'django.contrib.contenttypes',
'django.contrib.sessions',
'django.contrib.messages',
'django.contrib.staticfiles',
# 第三方
'rest_framework',
'corsheaders',
# 本项目
'health',
]
写第一个 APIView
编辑 health/views.py:
python
from rest_framework.views import APIView
from rest_framework.response import Response
class HealthView(APIView):
"""健康检查接口,供前端、第 92 讲的 K8s 探针、第 100 讲的部署脚本使用。"""
def get(self, request):
return Response({
"status": "ok",
"service": "shopx",
"version": "0.1.0",
})
配 URL
新建 health/urls.py:
python
from django.urls import path
from .views import HealthView
urlpatterns = [
path('health/', HealthView.as_view(), name='health'),
]
编辑 shopx/urls.py(根路由):
python
from django.contrib import admin
from django.urls import path, include
urlpatterns = [
path('admin/', admin.site.urls),
path('api/v1/', include('health.urls')),
]
注意:所有业务接口都挂在 /api/v1/ 下 。v1 是 API 版本号,第 80 讲会讲 API 版本管理的几种策略。
四、settings 分层(教学上的关键工程实践)
默认的 settings.py 是单文件,所有配置(数据库、邮件、缓存、第三方、调试)混在一起。生产级 Django 项目必须分层,否则换环境时改一堆地方容易出错。
拆分成 4 个文件
把 settings.py 删掉,新建 settings/ 目录:
bash
rm shopx/settings.py
mkdir shopx/settings
touch shopx/settings/__init__.py
生成 4 个文件:
text
shopx/
└── settings/
├── __init__.py
├── base.py # 公共配置(所有环境共享)
├── dev.py # 开发环境
├── test.py # 测试环境
└── prod.py # 生产环境
base.py(公共部分)
python
"""
ShopX Django 配置 - 基础配置(所有环境共享)
"""
from pathlib import Path
from decouple import config
BASE_DIR = Path(__file__).resolve().parent.parent.parent
# ========== 核心安全配置 ==========
SECRET_KEY = config('DJANGO_SECRET_KEY')
DEBUG = config('DJANGO_DEBUG', default=False, cast=bool)
ALLOWED_HOSTS = config(
'DJANGO_ALLOWED_HOSTS',
default='*',
cast=lambda v: [s.strip() for s in v.split(',')],
)
# ========== 应用注册 ==========
INSTALLED_APPS = [
'django.contrib.admin',
'django.contrib.auth',
'django.contrib.contenttypes',
'django.contrib.sessions',
'django.contrib.messages',
'django.contrib.staticfiles',
# 第三方
'rest_framework',
'corsheaders',
# 本项目
'health',
]
# ========== 中间件 ==========
MIDDLEWARE = [
# CORS必须在CommonMiddleware之前
'corsheaders.middleware.CorsMiddleware',
'django.middleware.security.SecurityMiddleware',
'django.contrib.sessions.middleware.SessionMiddleware',
'django.middleware.common.CommonMiddleware',
'django.middleware.csrf.CsrfViewMiddleware',
'django.contrib.auth.middleware.AuthenticationMiddleware',
'django.contrib.messages.middleware.MessageMiddleware',
'django.middleware.clickjacking.XFrameOptionsMiddleware',
]
ROOT_URLCONF = 'shopx.urls'
# ========== 模板 ==========
TEMPLATES = [
{
'BACKEND': 'django.template.backends.django.DjangoTemplates',
'DIRS': [],
'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',
],
},
},
]
WSGI_APPLICATION = 'shopx.wsgi.application'
ASGI_APPLICATION = 'shopx.asgi.application'
# ========== 数据库 ==========
DATABASES = {
'default': {
'ENGINE': 'django.db.backends.mysql',
'NAME': config('DB_NAME', default='shopx'),
'USER': config('DB_USER', default='root'),
'PASSWORD': config('DB_PASSWORD'),
'HOST': config('DB_HOST', default='127.0.0.1'),
'PORT': config('DB_PORT', default='3306'),
'OPTIONS': {
'charset': 'utf8mb4',
'init_command': "SET sql_mode='STRICT_TRANS_TABLES'",
},
}
}
# ========== 密码验证 ==========
AUTH_PASSWORD_VALIDATORS = [
{'NAME': 'django.contrib.auth.password_validation.UserAttributeSimilarityValidator'},
{'NAME': 'django.contrib.auth.password_validation.MinimumLengthValidator'},
{'NAME': 'django.contrib.auth.password_validation.CommonPasswordValidator'},
{'NAME': 'django.contrib.auth.password_validation.NumericPasswordValidator'},
]
# ========== 国际化 ==========
LANGUAGE_CODE = 'zh-hans'
TIME_ZONE = 'Asia/Shanghai'
USE_I18N = True
USE_TZ = True
# ========== 静态文件 ==========
STATIC_URL = 'static/'
STATIC_ROOT = BASE_DIR / 'staticfiles'
# ========== 媒体文件(用户上传) ==========
MEDIA_URL = 'media/'
MEDIA_ROOT = BASE_DIR / 'media'
DEFAULT_AUTO_FIELD = 'django.db.models.BigAutoField'
# ========== DRF ==========
REST_FRAMEWORK = {
'DEFAULT_PERMISSION_CLASSES': ['rest_framework.permissions.AllowAny'],
'DEFAULT_AUTHENTICATION_CLASSES': [
'rest_framework.authentication.SessionAuthentication',
'rest_framework_simplejwt.authentication.JWTAuthentication',
],
'DEFAULT_RENDERER_CLASSES': ['rest_framework.renderers.JSONRenderer'],
'DEFAULT_PARSER_CLASSES': ['rest_framework.parsers.JSONParser'],
'DEFAULT_PAGINATION_CLASS': 'rest_framework.pagination.PageNumberPagination',
'PAGE_SIZE': 20,
}
# ========== CORS(M0级别够用)==========
CORS_ALLOWED_ORIGINS = [
'http://127.0.0.1:5173',
'http://localhost:5173',
]
# ========== 存储 ==========
STORAGES = {
"default": {
"BACKEND": "django.core.files.storage.FileSystemStorage",
},
"staticfiles": {
"BACKEND": "django.contrib.staticfiles.storage.StaticFilesStorage",
},
}
这段代码使用了python-decouple库,需要进行配置。后面第五节会单独讲。
dev.py
python
"""开发环境配置"""
from .base import *
DEBUG = True
ALLOWED_HOSTS = ['*']
# 控制台邮件后端,方便开发期看邮件内容
EMAIL_BACKEND = 'django.core.mail.backends.console.EmailBackend'
test.py
python
"""测试环境配置"""
from .base import *
DEBUG = False
# 用内存数据库跑测试,不污染真实数据
DATABASES = {
'default': {
'ENGINE': 'django.db.backends.sqlite3',
'NAME': ':memory:',
}
}
prod.py
python
"""生产环境配置(占位)"""
from .base import *
DEBUG = False
# ALLOWED_HOSTS必须在.env里配
切换环境
通过 DJANGO_SETTINGS_MODULE 环境变量:
bash
# 开发
export DJANGO_SETTINGS_MODULE=shopx.settings.dev
python manage.py runserver
# 测试
export DJANGO_SETTINGS_MODULE=shopx.settings.test
python manage.py test
# 生产
export DJANGO_SETTINGS_MODULE=shopx.settings.prod
gunicorn shopx.wsgi:application
为什么不直接用django-environ?
它功能更强,但配置文件要写一堆env()调用,对零基础读者不友好。
python-decouple配合.env文件足够本专栏用,后面生产部署时再考虑迁移。
五、配置python-decouple
python-decouple是从.env文件读配置的小工具。比os.environ多了几个能力:
- 自动处理
boolintlist类型转换 - 默认值
.env不存在时报错而不是悄悄用空值
项目根目录建 .env
⚠️ 必须放在
shopx/.gitignore已忽略的路径下 。本专栏把.env放在backend/.env(不进 git)。
ini
# Django
DJANGO_SECRET_KEY=dev-secret-key-change-me-in-prod
DJANGO_DEBUG=True
DJANGO_ALLOWED_HOSTS=*
# MySQL(密码要改)
DB_NAME=shopx
DB_USER=root
DB_PASSWORD=your_strong_password_here
DB_HOST=127.0.0.1
DB_PORT=3306
# Redis
REDIS_URL=redis://127.0.0.1:6379/0
创建数据库
bash
mysql -uroot -p
sql
CREATE DATABASE shopx DEFAULT CHARACTER SET utf8mb4 COLLATE utf8mb4_unicode_ci;
SHOW DATABASES;
EXIT;
💡
utf8mb4_unicode_ci是更精确的排序规则(比utf8mb4_general_ci准确但稍慢),适合需要中文排序的电商场景。
跑迁移
bash
python manage.py migrate
输出类似:
text
Operations to perform:
Apply all migrations: admin, auth, contenttypes, sessions
Running migrations:
Applying contenttypes.0001_initial... OK
Applying auth.0001_initial... OK
...
迁移会自动建好django_*开头的内置表(admin、auth、sessions 等)。
验证表
bash
mysql -uroot -p shopx -e "SHOW TABLES;"
应该看到 auth_user、django_session、django_migrations 等表。
六、DRF配置详解
DRF(Django REST Framework)是Django生态里最主流的REST API框架。本节把它的几个关键配置讲透。
全局配置项
已经在base.py中配置,这里再强调几个关键项:
python
REST_FRAMEWORK = {
'DEFAULT_PERMISSION_CLASSES': ['rest_framework.permissions.AllowAny'],
'DEFAULT_AUTHENTICATION_CLASSES': [
'rest_framework.authentication.SessionAuthentication',
'rest_framework_simplejwt.authentication.JWTAuthentication',
],
'DEFAULT_RENDERER_CLASSES': ['rest_framework.renderers.JSONRenderer'],
'DEFAULT_PARSER_CLASSES': ['rest_framework.parsers.JSONParser'],
'DEFAULT_PAGINATION_CLASS': 'rest_framework.pagination.PageNumberPagination',
'PAGE_SIZE': 20,
}
各项含义
DEFAULT_PERMISSION_CLASSES:默认权限。M0阶段先用AllowAny(任何人都能访问),后面会收紧为IsAuthenticatedDEFAULT_AUTHENTICATION_CLASSES:默认认证方式。Session用于Django Admin登录,JWT用于API调用DEFAULT_RENDERER_CLASSES:只输出JSON(不要HTML调试页面)DEFAULT_PARSER_CLASSES:只接受JSON入参(不要form-urlencoded)DEFAULT_PAGINATION_CLASS:默认分页器,列表接口自动分页,每页20条PAGE_SIZE:默认每页条数
DRF 三件套
DRF把Web API抽象成三个层次:
- Serializer(序列化器)------ 数据格式转换 + 校验
- View(视图)------ 业务逻辑,接收请求、返回响应
- Router(路由器)------ URL路由(自动生成5个端点)
本讲只用到APIView,是最底层的写法。后面会升级到ViewSet + Router,代码量减少70%。
七、CORS预配置(M0级别)
我们在Vite里配了devServer.proxy------开发期能解决跨域。但生产环境(前端部署到shopx.com、后端在api.shopx.com)必须靠真正的CORS头。
安装与配置
django-cors-headers在INSTALLED_APPS和MIDDLEWARE都注册过了(见base.py)。CORS_ALLOWED_ORIGINS列出了允许跨域的前端源。
工作原理
浏览器看到http://shopx.com调http://api.shopx.com/api/v1/health/时:
- 浏览器发OPTIONS预检请求
- 后端检查
Origin头是否在白名单 - 在白名单里 → 返回
Access-Control-Allow-Origin: http://shopx.com - 浏览器放行真实请求
M0级别配的就够开发用了
完整CORS原理(含Cookie携带、复杂请求、Origin校验原理)。
八、跑起来验证
启动服务
bash
# 确认虚拟环境已激活、依赖已装
export DJANGO_SETTINGS_MODULE=shopx.settings.dev
python manage.py runserver 0.0.0.0:8000
终端输出:
text
Watching for file changes with StatReloader
Starting development server at http://0.0.0.0:8000/
Quit the server with CONTROL-C.
测试三个端点
1. 健康检查接口:
浏览器打开 http://127.0.0.1:8000/api/v1/health/,应该看到:
json
{
"status": "ok",
"service": "shopx",
"version": "0.1.0"
}
2. Django Admin登录页:
浏览器打开http://127.0.0.1:8000/admin/,看到登录页。账号还没建,先用命令行建一个superuser:
bash
python manage.py createsuperuser
# 输入用户名、邮箱、密码
然后用这个账号登录Admin,能看到health app已经在管理界面里(虽然暂时空)。
3. 前后端联调:
第4讲的前端只渲染了静态页面,还没调过后端。
这一节我们把App.vue改一版,让它启动时请求/api/v1/health/,把后端返回的版本号显示在页面上。
这是整个专栏第一次前后端真实通信,也是M0里程碑最关键的验证。
3.1. 修改 frontend/src/App.vue
vue
<script setup lang="ts">
import { ref, onMounted } from 'vue'
interface HealthResponse {
status: string
service: string
version: string
}
const year = new Date().getFullYear()
const health = ref<HealthResponse | null>(null)
const error = ref<string | null>(null)
onMounted(async () => {
try {
// 走 Vite proxy,实际请求 http://127.0.0.1:8000/api/v1/health/
const res = await fetch('/api/v1/health/')
if (!res.ok) throw new Error(`HTTP ${res.status}`)
health.value = await res.json()
} catch (e) {
error.value = e instanceof Error ? e.message : String(e)
}
})
</script>
<template>
<div class="hello">
<div class="brand">ShopX</div>
<h1>Hello ShopX</h1>
<p class="subtitle">从零到上线 · 全栈电商项目</p>
<div v-if="health" class="health ok">
✅ 后端连接成功 · {{ health.service }} v{{ health.version }}
</div>
<div v-else-if="error" class="health err">
❌ 后端连接失败:{{ error }}
</div>
<div v-else class="health loading">
⏳ 正在连接后端...
</div>
<p class="muted">© {{ year }} · 第 5 讲里程碑</p>
</div>
</template>
<style scoped>
.hello {
min-height: 100vh;
display: flex;
flex-direction: column;
align-items: center;
justify-content: center;
background: linear-gradient(135deg, #0f1b2d 0%, #1a2a44 100%);
color: #ffffff;
font-family: -apple-system, BlinkMacSystemFont, 'Segoe UI', 'PingFang SC', sans-serif;
}
.brand {
font-size: 18px;
letter-spacing: 6px;
color: #ffb020;
margin-bottom: 24px;
}
h1 {
font-size: 64px;
margin: 0 0 16px;
font-weight: 500;
}
.subtitle {
font-size: 18px;
color: #cbd5e1;
margin: 32px 0;
}
.health {
padding: 10px 20px;
border-radius: 8px;
font-size: 15px;
margin-bottom: 40px;
}
.health.ok {
background: rgba(34, 197, 94, 0.15);
color: #4ade80;
}
.health.err {
background: rgba(239, 68, 68, 0.15);
color: #f87171;
}
.health.loading {
background: rgba(148, 163, 184, 0.15);
color: #94a3b8;
}
.muted {
color: #8a93a6;
font-size: 14px;
}
</style>
3.2. 确认两个服务都在跑
bash
# 终端 1:后端
cd ~/workspace/shopx/backend
source ../.venv/bin/activate
export DJANGO_SETTINGS_MODULE=shopx.settings.dev
python manage.py runserver 0.0.0.0:8000
# 终端 2:前端
cd ~/workspace/shopx/frontend
pnpm dev
3.3. 验证联调
浏览器打开http://127.0.0.1:5173/,你应该看到:
text
ShopX
Hello ShopX
从零到上线 · 全栈电商项目
✅ 后端连接成功 · shopx v0.1.0
© 2026 · 第 5 讲里程碑
打开开发者工具 → Network面板,能看到一条health/请求:
- Request URL:
http://127.0.0.1:5173/api/v1/health/ - Status:
200 - Response:
{"status":"ok","service":"shopx","version":"0.1.0"}
请求地址是5173不是8000 ------这正是Vite proxy在起作用。Vite收到/api/v1/health/后,转发给http://127.0.0.1:8000,浏览器完全无感,也就没有跨域问题。
3.4. 如果看到「❌ 后端连接失败」
按顺序排查:
| 现象 | 原因 | 解决 |
|---|---|---|
HTTP 404 |
后端URL没挂上 | 检查shopx/urls.py有path('api/v1/', include('health.urls')) |
Failed to fetch |
后端没跑,或proxy没配 | 确认8000端口能访问;检查vite.config.ts的server.proxy |
| CORS报错 | 请求没走proxy,直接打到8000 | 确认fetch写的是/api/v1/health/,不是http://127.0.0.1:8000/api/v1/health/ |
💡 关键 :前端代码里永远写相对路径
/api/v1/...,不要写完整后端地址。开发期靠Vite proxy,生产期靠Nginx反代,前端代码不用改。
3.5. 提交这一节的改动
bash
cd ~/workspace/shopx
git add frontend/src/App.vue
git commit -m "feat(frontend): 第 005 讲 App.vue 接入 health 接口完成联调"
---
## 九、生成requirements.txt锁版本
`pip freeze` 导出所有依赖到 `requirements.txt`:
```bash
pip freeze > requirements.txt
requirements.txt 长这样:
text
Django==6.1
djangorestframework==3.18.x
djangorestframework-simplejwt==5.5.x
django-cors-headers==4.9.x
python-decouple==3.8
mysqlclient==2.2.x
redis==6.2.x
celery==5.6.x
💡 小版本号(
x)随安全补丁更新,不影响教程内容。之前已说明:本专栏锁定大版本,小版本跟随最新补丁。
一键起项目脚本
新建backend/run_dev.sh:
bash
#!/usr/bin/env bash
set -e
cd "$(dirname "$0")"
export DJANGO_SETTINGS_MODULE=shopx.settings.dev
python manage.py runserver 0.0.0.0:8000
bash
chmod +x run_dev.sh
下次启动直接bash run_dev.sh。
十、提交与打tag
按第3讲的提交规范,本讲至少两个commit:
bash
cd ~/workspace/shopx
# 第一个commit:Django工程初始化 + settings分层
git add backend/manage.py backend/shopx backend/requirements.txt
git commit -m "feat(backend): 第 005 讲 初始化 Django 工程与 settings 分层"
# 第二个commit:health app + DRF + CORS配置
git add backend/health backend/.env.example backend/run_dev.sh
git commit -m "feat(backend): 第 005 讲 health 接口与 DRF/CORS 接入"
# 推送特性分支
git push -u origin feature/lecture-005-backend-scaffold
合并到develop:
bash
git switch develop
git merge --squash feature/lecture-005-backend-scaffold
git commit -m "feat(backend): 第 005 讲 Django 5 后端骨架与 DRF 接入"
git tag lecture/005
git push origin develop
git push origin lecture/005
删掉feature分支
bash
git branch -d feature/lecture-004-frontend-scaffold
#删除远程分支
git push origin --delete feature/lecture-004-frontend-scaffold
十一、本讲作业
- 跑通
/api/v1/health/ - 创建superuser并登录
/admin/ - 故意把
.env里的DB_PASSWORD改错,看报错信息,再改回来------体验一下「密码错」的报错长什么样 - 试
bash run_dev.sh一键启动 - 完整跑一次「前5讲里程碑」自检 :
- 浏览器打开
http://127.0.0.1:5173/看到Hello ShopX - 浏览器打开
http://127.0.0.1:8000/api/v1/health/看到ok - 浏览器开发者工具Network看到前端成功调通后端
- 浏览器打开
- 截图三个画面,合成一张「M0里程碑成就」图发评论区
十二、常见报错速查表
| 报错 | 原因 | 解决 |
|---|---|---|
django-admin: command not found |
没装Django或没激活虚拟环境 | pip install "Django>=6.1,<6.2",确认终端前缀有(shopx) |
mysqlclient装失败:mysql_config not found |
macOS缺mysql-client | brew install mysql-client pkg-config,加export PKG_CONFIG_PATH="/opt/homebrew/opt/mysql-client/lib/pkgconfig" |
django.db.utils.OperationalError: (1045, "Access denied") |
MySQL用户名/密码错 | 改.env里的DB_USER / DB_PASSWORD |
Unknown database 'shopx' |
数据库没建 | mysql -uroot -p -e "CREATE DATABASE shopx DEFAULT CHARACTER SET utf8mb4;" |
CORS报错No 'Access-Control-Allow-Origin' header |
前端访问后端但CORS_ALLOWED_ORIGINS没配 |
检查settings/base.py里的origins列表 |
ModuleNotFoundError: No module named 'decouple' |
python-decouple没装 | pip install python-decouple |
ALLOWED_HOSTS报错Invalid HTTP_HOST |
ALLOWED_HOSTS没收当前访问的域名 |
dev环境允许 ['*'],prod必须明确写域名 |
ModuleNotFoundError: No module named 'health' |
health app没注册 | INSTALLED_APPS里加'health' |
| 启动后看到的是Django欢迎页而不是JSON | URL没挂上 | 检查shopx/urls.py是否有path('api/v1/', include('health.urls')) |
十三、术语自查报告
- ✅ Django 6.1 / DRF 3.18.x 精确版本
- ✅
startproject shopx .末尾的点含义写清 - ✅
INSTALLED_APPS/MIDDLEWARE大小写正确 - ✅
MIDDLEWARE顺序:CORS必须在CommonMiddleware之前 - ✅
utf8mb4(不是utf8)写全 - ✅
APIView/Response来自rest_framework - ✅
python-decouple名字写对(不是python_decouple) - ✅
DJANGO_SETTINGS_MODULE环境变量名写对 - ✅
ALLOWED_HOSTS不能用*在生产 - ✅
mysqlclient装失败原因(mysql_config not found)写对 - ✅ CORS是「跨源资源共享」(Cross-Origin Resource Sharing)
- ✅
pip freeze > requirements.txt锁版本 - ✅ WSGI同步 / ASGI异步区别一句话写明
- ✅ API版本号
/api/v1/写明意义
自查通过。无禁用词。
最后:M0 里程碑,你已解锁
如果你跟着跑通了health接口,评论区打卡一句:
第005讲签到,M0里程碑已解锁
- 点赞:让更多正在搭后端的人看到
- 收藏:配settings分层、DRF配置时随时回查
- 关注:追更不迷路
我们第6讲见。