零基础入门python31:Django商城第一步——创建项目并跑通第一个请求

零基础入门python31:Django商城第一步------创建项目并跑通第一个请求

一、上一篇课后练习讲解

Python 基础阶段最后一个练习是把命令行任务管理器拆成多个模块。参考做法是把"读取输入、校验、业务处理、保存文件"分开,再用 python -m 从项目根目录启动。Django 项目也遵循同样的思路:配置、路由、业务应用各有职责。

上一篇课后练习完整答案

上一篇练习的要求已落实到下面完整文件;先运行项目测试,再用 curl 对照状态码和数据库持久化结果

答案要点:README 验收从空目录创建虚拟环境、迁移、测试和冒烟;记录版本、状态码和只读数据库等故障结果。

文件:README.md

完整参考答案文件

完整文件:README.md

text 复制代码
# Flask Ledger 验收
python -m pip install -r requirements.txt
flask --app run.py db upgrade
python -m pytest -q
flask --app run.py run

完整参考答案文件

本篇对应的交付源码完整文件:flask-ledger/tests/test_app.py

python 复制代码
def test_health(client):
    assert client.get("/api/health").get_json() == {"status": "ok"}


def test_register_login_and_me(client):
    response = client.post("/api/auth/register", json={"email": "A@example.com", "password": "password123"})
    assert response.status_code == 201
    assert client.post("/api/auth/login", json={"email": "a@example.com", "password": "password123"}).status_code == 200
    assert client.get("/api/auth/me").get_json()["email"] == "a@example.com"


def test_ledger_flow(logged_client):
    category = logged_client.post("/api/categories", json={"name": "餐饮"}).get_json()
    created = logged_client.post("/api/transactions", json={
        "kind": "expense", "amount": "28.50", "category_id": category["id"],
        "happened_on": "2026-08-06", "note": "午饭",
    })
    assert created.status_code == 201
    assert created.get_json()["amount"] == "28.50"
    items = logged_client.get("/api/transactions").get_json()["items"]
    assert len(items) == 1
    stats = logged_client.get("/api/statistics/monthly?month=2026-08").get_json()
    assert stats["expense"] == "28.50"
    assert logged_client.delete(f"/api/transactions/{items[0]['id']}").status_code == 204


def test_users_cannot_share_categories(client):
    client.post("/api/auth/register", json={"email": "first@example.com", "password": "password123"})
    client.post("/api/auth/login", json={"email": "first@example.com", "password": "password123"})
    category = client.post("/api/categories", json={"name": "工资"}).get_json()
    client.post("/api/auth/logout")
    client.post("/api/auth/register", json={"email": "second@example.com", "password": "password123"})
    client.post("/api/auth/login", json={"email": "second@example.com", "password": "password123"})
    response = client.post("/api/transactions", json={"kind": "income", "amount": "100", "category_id": category["id"]})
    assert response.status_code == 404

验收命令:python -m pytest -q(Django 项目使用 python manage.py test)。预期测试通过;若失败先检查迁移、配置和事务回滚。

二、本篇完成什么

今天不急着写商品和订单。我们先完成一件能验证环境的事情:创建商城项目,启动开发服务器,访问 /api/health/,看到明确的 JSON 响应。

如果这一步没有跑通,后面所有模型、迁移和接口都会建立在错误环境上。

三、Django项目到底是什么

Django 项目由"配置容器"和"业务应用"组成:

config 不应该保存商品业务;shop 不应该偷偷读取命令行参数。这样拆开后,部署配置变化时不需要修改订单代码。

四、创建项目

在课程工作目录执行:

powershell 复制代码
python -m venv .venv
.venv\\Scripts\\activate
pip install "Django>=5.0,<6" djangorestframework
django-admin startproject config django-shop
cd django-shop
python manage.py startapp shop

如果 django-admin 找不到,说明虚拟环境没有激活;如果 ModuleNotFoundError: django,说明依赖安装到了另一个 Python。

五、配置应用

1. config/settings.py

python 复制代码
INSTALLED_APPS = [
    # Django 自带用户、Session 和 Admin,商城会直接复用它们。
    'django.contrib.admin',
    'django.contrib.auth',
    'django.contrib.contenttypes',
    'django.contrib.sessions',
    'django.contrib.messages',
    'django.contrib.staticfiles',
    'rest_framework',
    'shop',
]

REST_FRAMEWORK = {
    # 未登录用户可以浏览商品;需要购买时再在具体视图上收紧权限。
    'DEFAULT_PERMISSION_CLASSES': ['rest_framework.permissions.AllowAny'],
}

INSTALLED_APPS 决定 Django 是否加载模型、迁移和 Admin。把 shop 写进去后,Django 才知道这个应用有数据库模型。

2. shop/views.py

python 复制代码
from rest_framework.response import Response
from rest_framework.views import APIView


class HealthView(APIView):
    """给容器编排和人工检查使用的轻量健康检查。"""

    authentication_classes = []
    permission_classes = []

    def get(self, request):
        # 健康检查不查询业务表,避免数据库故障时把真实原因隐藏掉。
        return Response({'status': 'ok', 'service': 'django-shop'})

这里没有把数据库查询放进健康检查,因为第一篇只验证 Web 进程是否能响应。后面会增加 /api/ready/,专门检查数据库是否可用;区分 liveness 和 readiness 是部署时很重要的设计。

3. shop/urls.py

python 复制代码
from django.urls import path
from .views import HealthView

urlpatterns = [
    path('health/', HealthView.as_view(), name='health'),
]

4. config/urls.py

python 复制代码
from django.contrib import admin
from django.urls import include, path

urlpatterns = [
    path('admin/', admin.site.urls),
    # 总路由只负责把 /api/ 交给 shop,不实现业务细节。
    path('api/', include('shop.urls')),
]

六、启动和查看结果

powershell 复制代码
python manage.py check
python manage.py migrate
python manage.py runserver 127.0.0.1:8000

另开一个终端:

powershell 复制代码
curl http://127.0.0.1:8000/api/health/

预期响应:

json 复制代码
{"status":"ok","service":"django-shop"}

check 只检查配置,migrate 创建 Django 自带的用户和 Session 表,runserver 启动开发服务器。三条命令作用不同,不要把 runserver 当成迁移命令。

七、常见错误排查

现象 原因 处理
No module named django 没有使用虚拟环境里的 Python 重新激活 .venv 并运行 python -m pip install
404 /api/health 总路由没有 include shop.urls 检查 config/urls.pypath('api/', ...)
Apps aren't loaded yet 在 Django 启动前导入模型 把模型导入放进视图或正确的 Django 入口
浏览器能访问、curl 失败 端口或地址不一致 确认 runserver 输出的监听地址

八、本篇验收

powershell 复制代码
python manage.py check
python manage.py test
curl http://127.0.0.1:8000/api/health/

验收标准:system check 无问题;测试通过;健康检查返回 200 和 JSON;删除健康检查视图中的注释不会影响行为,但删除路由会导致 404。

九、课后练习

增加 /api/version/ 接口,返回 {'version': '0.1.0'},并写一个 Django 测试断言状态码、响应类型和字段值。下一篇会在这个项目上创建 Category 和 Product 模型,并解释迁移文件到底做了什么。

项目增量:商城目录和第一个请求

本篇目标不是记住 startproject 命令,而是理解 settings、urls、app 和模板各自负责什么。创建 shop app 后,把首页路由接到一个明确的 view,再用 Django test client 验收状态码。

python 复制代码
from django.http import HttpResponse

def home(request):
    return HttpResponse('shop is running')

验收 GET / 返回 200;若出现 404,依次检查项目 urls 是否 include shop.urls、路径是否带结尾斜杠以及应用是否加入 INSTALLED_APPS。课后练习增加 /health JSON 响应,下一篇创建商品模型。

十、把第一次请求做成可维护的接口

健康检查不应返回一段随意文本,推荐固定 JSON 契约并写测试:

python 复制代码
from django.http import JsonResponse

def health(request):
    return JsonResponse({"status": "ok", "service": "django-shop", "version": "0.1.0"})
python 复制代码
from django.test import TestCase

class HealthTests(TestCase):
    def test_health_contract(self):
        response = self.client.get("/api/health/")
        self.assertEqual(response.status_code, 200)
        self.assertEqual(response.json()["status"], "ok")
        self.assertEqual(response["Content-Type"], "application/json")

manage.py check 检查配置,migrate 管理数据库结构,runserver 才是启动 HTTP 服务;三者分工不同。开发阶段先让 /api/health/ 稳定,后面每次增加模型、Serializer 或事务,都可以用它区分"进程坏了"与"业务依赖坏了"。本篇练习完成后,下一篇会在同一项目中加入 Category/Product,并用迁移而不是手工建表。

本篇结束:完整模块文件

下面是交付项目中真实存在的完整文件 django-shop/config/urls.py。它覆盖本篇新增逻辑以及前文已经完成的依赖代码;复制单个函数会丢失上下文,因此这里提供整份文件。

python 复制代码
"""
URL configuration for config project.

The `urlpatterns` list routes URLs to views. For more information please see:
    https://docs.djangoproject.com/en/5.2/topics/http/urls/
Examples:
Function views
    1. Add an import:  from my_app import views
    2. Add a URL to urlpatterns:  path('', views.home, name='home')
Class-based views
    1. Add an import:  from other_app.views import Home
    2. Add a URL to urlpatterns:  path('', Home.as_view(), name='home')
Including another URLconf
    1. Import the include() function: from django.urls import include, path
    2. Add a URL to urlpatterns:  path('blog/', include('blog.urls'))
"""
from django.contrib import admin
from django.urls import include, path

urlpatterns = [
    path('admin/', admin.site.urls),
    path('api/', include('shop.urls')),
]
相关推荐
孫治AllenSun13 分钟前
【LangChain4J-06】Prompt 工程与模板化开发
开发语言·python·prompt
qq_4260039614 分钟前
多语言新增语种全量测试策略
前端·javascript·python·pycharm·自动化
AuLuo-17 分钟前
SearXNG 物理机部署搭建免费搜索引擎服务
python·搜索引擎
言乐633 分钟前
Python关于老游复刻与创新2
前端·javascript·css·python·css3
青 春 记 忆9 小时前
Dify Docker Compose 通用无损升级指南:从备份、双版本预演到切换与回滚
运维·人工智能·python·docker·容器
GlueNa2SiO39 小时前
03-Flask模板引擎Jinja2详解
笔记·python·flask
秋饼11 小时前
JDK 27 企业级 AI 服务落地实战:G1 默认、紧凑对象头、后量子 TLS 与 JFR 脱敏全解析
java·ai·技术分享·后端开发
临沂GEO11 小时前
GEO搜索优化科普|正规地理位置流量运营入门指南
大数据·人工智能·python·流量运营
大模型码小白11 小时前
Spring AI Tool 实现自然语言操作 MySQL 数据库详解
服务器·开发语言·数据库·人工智能·python·mysql·spring