Django服务端渲染实战包:含路由、视图、模板与基础计算逻辑的可运行全栈示例

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

简介:一个开箱即用的Django入门项目,专注传统服务端渲染流程,不引入任何前端框架。通过简单的URL配置(urls.py)将请求分发到视图函数(views.py),视图调用calculate.py完成基础业务计算,并把结果连同上下文数据传入hello.html和.html等HTML模板,由Django内置模板引擎完成最终渲染。项目结构完整,包含标准Django应用组件:models.py定义数据模型,admin.py支持后台管理,apps.py声明应用配置,migrations目录管理数据库迁移,templates文件夹集中存放所有HTML模板,settings.py提供调试与部署相关设置,manage.py用于常规命令操作,wsgi.py和asgi.py分别适配WSGI/ASGI服务器部署。配套SQLite数据库(db.sqlite3)已初始化,虚拟环境(venv)和开发配置(.gitignore、.idea、pycache)均已就位,不影响运行。适合新手动手实践请求生命周期、URL映射、视图响应、模板变量与标签、静态资源组织等核心Web开发环节。

1. 项目概述:为什么一个“过时”的服务端渲染示例,反而成了新手最该啃下的第一块硬骨头?

你点开这个项目,看到 hello.html、urls.py、views.py 这些文件名,可能第一反应是:“这不就是十年前的老古董吗?现在谁还用 Django 直接 render HTML?不都上 Vue + REST API 了?”——我第一次带实习生时,也听到过一模一样的质疑。但后来我们花了整整三周,把一个本该两天搞定的后台管理页,反复推倒重来:先用 Vue 写一遍,接口调不通、状态错乱、跨域头疼;再用纯 Django 模板写一遍,{{ result }} 一行就显示计算结果,{% if user.is_authenticated %} 两行搞定权限判断,{% for item in items %} 循环列表干净利落。最后实习生盯着浏览器里那个没有 JS 报错、没有网络请求瀑布流、却稳稳当当跑起来的页面,说了句:“原来‘简单’不是功能少,而是逻辑全在眼皮底下。”

这就是这个项目存在的全部意义:它不炫技,不堆栈,不制造抽象层,它把 Web 开发最底层的“请求-响应”链条,像拆解一台机械钟表一样,一颗齿轮、一根游丝地摊在你面前。关键词里写的 Django模板、服务端渲染、视图函数、路由配置、HTML渲染,每一个都不是孤立概念,而是一条环环相扣的流水线——用户敲下回车,DNS 解析、TCP 握手、HTTP 请求抵达 Django 的 urls.py(这是第一道闸门),它根据正则或路径匹配,把请求“扔”给 views.py 里的某个函数(这是第二道闸门),这个函数调用 calculate.py 做加减乘除(这是业务核心),再把数字、字符串、列表一股脑塞进字典,传给 render() 函数(这是第三道闸门),render() 拿着这个字典,打开 hello.html,找到 {{ name }} 就替换成字典里的值,遇到 {% for %} 就循环渲染 HTML 片段,最后把拼好的完整 HTML 字符串,通过 HTTP 响应体,原封不动吐给浏览器(这是最后一道闸门)。整个过程,没有 AJAX,没有 JSON.parse,没有虚拟 DOM diff,只有 Python 代码和 HTML 字符串之间最朴素的“填空游戏”。

所以它适合谁?不是适合想立刻上线 SaaS 产品的创业者,而是适合那些刚学完 Python 基础语法、对着 print("Hello World") 欢呼雀跃,却对“网页怎么动起来”毫无头绪的新手;是适合那些被 React 的 useState 和 useEffect 绕晕、搞不清“数据驱动视图”到底驱动了什么的转行者;是适合那些在公司维护着十年老后台、天天改 admin.py 却从没自己写过 urls.py 的“半路出家”运维。它不承诺让你成为全栈大神,但它能确保你亲手拧紧每一颗螺丝后,清楚知道这台机器为什么能转,以及哪颗螺丝松了会发出异响。接下来,我们就从这条流水线的起点开始,一节一节地拆解、复现、踩坑、验证。

2. 整体架构与设计思路:为什么坚持“传统”,而不是拥抱“现代”?

2.1 核心设计哲学:拒绝抽象,拥抱可见性

这个项目的骨架,严格遵循 Django 官方文档里最经典的“Polls Tutorial”范式,但做了更极致的简化与聚焦。它的目录结构不是为了展示“企业级应用该长什么样”,而是为了回答一个最根本的问题:“当我在浏览器地址栏输入 http://127.0.0.1:8000/calculate/ 并按下回车,Django 内部到底发生了什么?” 因此,所有组件的存在,都服务于这个单一目标:

  • urls.py 是唯一的“交通指挥中心”,它不玩花哨的 path() 和 re_path() 混搭,只用最基础的 path('calculate/', views.calculate_view, name='calculate'),清晰表明“这个 URL 路径,必须交给 views.py 里的 calculate_view 函数处理”。没有 include(),没有子路由,避免新手在 blog/urls.py 和根 urls.py 之间迷失。
  • views.py 是纯粹的“业务调度员”,里面只有两个函数:home_view(负责渲染首页 hello.html)和 calculate_view(负责接收表单、调用计算、渲染结果页 result.html)。它不做任何数据库操作(models.py 是空的,仅作占位),不引入第三方库,所有逻辑都在 calculate.py 里,保证视图层极度轻量。
  • calculate.py 是独立的“计算器模块”,它被设计成一个可测试、可替换的纯函数集合。比如 def add(a: float, b: float) -> float:,输入两个数,返回一个数,没有任何副作用。这样做的好处是,当你未来想把它换成调用外部 API 或读取数据库时,只需修改这一小块,views.py 完全不用动。
  • templates/ 目录下只有两个 HTML 文件:hello.html(带一个表单,提交到 /calculate/)和 result.html(显示计算结果)。它们不使用任何 Bootstrap 或 Tailwind CSS,只用最原始的 <h1>、<p>、<form> 标签,连内联样式都刻意避免,强迫你把注意力放在 Django 模板语法本身——{{ result }} 怎么显示变量,{% if result > 100 %} 怎么做条件判断,{% for step in steps %} 怎么循环渲染步骤说明。

这种“反潮流”的设计,其底层逻辑是:新手最大的障碍,从来不是技术本身的复杂度,而是“不可见性”带来的失控感。 当你用 Vue 写一个按钮点击事件,背后是事件总线、响应式系统、虚拟 DOM 渲染三重抽象;而在这个项目里,点击按钮 → 提交表单 → 触发 calculate_view → 执行 add() → 返回 result.html → 浏览器显示 {{ result }},每一步都对应着一个你能在文件系统里直接打开、编辑、打断点的 Python 或 HTML 文件。这种“所见即所得”的确定性,是建立信心的第一块基石。

2.2 关键技术选型背后的“为什么”

为什么用 SQLite 而不是 PostgreSQL?因为新手不需要折腾数据库安装、用户权限、连接池配置。db.sqlite3 就是一个文件,双击就能用文本编辑器打开看里面存了啥(虽然内容是二进制,但至少你知道它就在那儿)。settings.py 里 DATABASES 配置只有四行,删掉注释后只剩两行:

'DATABASES': {
    'default': {
        'ENGINE': 'django.db.backends.sqlite3',
        'NAME': BASE_DIR / 'db.sqlite3',
    }
}

没有密码、没有端口、没有主机名,零配置启动。

为什么 models.py 是空的?因为本项目的核心教学目标是“渲染流程”,而非“数据建模”。引入模型意味着要学 makemigrations、migrate、ModelForm,这些都会把焦点从“HTML 怎么被填满”转移到“数据库表怎么创建”。等你彻底搞懂 render() 怎么把字典变成 HTML 后,再往里加一个 CalculationHistory 模型记录每次计算,就是水到渠成的事。

为什么 static/ 目录不存在?因为本项目刻意剥离了“静态资源管理”这个独立议题。所有 CSS 和 JS 都以内联方式写在 HTML 的 <style> 和 <script> 标签里(如果需要的话),或者干脆不用。这样,你就不会在 STATIC_URL、STATICFILES_DIRS、collectstatic 这些概念里打转。记住,一个清晰的教学示例,必须敢于做减法,而不是堆砌所有“应该有”的东西。

2.3 与“现代”全栈方案的本质区别

很多人误以为“服务端渲染”就是“落后”,其实它是一种截然不同的架构哲学。我们可以用一个生活化的类比来理解:

  • Vue/React SPA(单页应用) 就像一家“自助餐厅”:你第一次进门,厨房(服务器)给你一份完整的菜单(HTML + JS bundle),然后你所有的点餐、取餐、结账动作,都在这个菜单页面内完成。厨房只负责提供食材(API 数据),不参与你的用餐流程。优点是流畅、交互强;缺点是第一次加载慢,SEO 不友好,调试时你得在浏览器控制台和后端日志之间来回切换。

  • Django 服务端渲染 则像一家“传统中餐馆”:你点菜(发送 HTTP 请求),厨师(Django 视图)根据你的要求(URL 和参数),现场炒一道新菜(生成新的 HTML),装盘(HTTP 响应)后端给你。每一道菜都是独立的、完整的、即拿即食的。优点是首屏快、SEO 天然好、逻辑集中、调试直观;缺点是每次交互都要刷新页面,大规模复杂交互不如 SPA 灵活。

这个项目选择后者,不是因为它更好,而是因为它更透明、更易教、更易学。它把“Web 是什么”这个问题,用最朴实的方式回答了:Web 就是客户端(浏览器)和服务器(Django)之间,基于 HTTP 协议,不断交换 HTML 文本的过程。其他一切,都是在这个基础上的优化与延伸。

3. 核心细节解析与实操要点:从 urls.py 到 hello.html 的逐行拆解

3.1 路由配置 (urls.py):URL 是如何被“翻译”成 Python 函数的?

Django 的路由系统,本质上是一个“URL 字符串”到“Python 可调用对象”的映射字典。urls.py 就是这个字典的声明文件。我们来看项目中最关键的一行:

# urls.py
from django.contrib import admin
from django.urls import path
from blog import views  # 注意:这里导入的是 blog 应用下的 views 模块

urlpatterns = [
    path('admin/', admin.site.urls),
    path('', views.home_view, name='home'),           # 根路径,指向 home_view
    path('calculate/', views.calculate_view, name='calculate'),  # 计算路径,指向 calculate_view
]

这段代码的执行逻辑,远比表面看起来深刻。当你访问 http://127.0.0.1:8000/calculate/ 时,Django 的 URLResolver 会拿着这个字符串,从上到下依次匹配 urlpatterns 列表里的每一个 path()。匹配过程不是简单的字符串相等,而是基于 path() 函数内部的正则引擎(path() 使用的是更简洁的路径转换器,但底层仍是正则)。它会检查:
- admin/?不匹配,因为路径是 calculate/。
- 空字符串 ''?不匹配,因为路径是 calculate/。
- calculate/?完全匹配!于是,Django 就“决定”将这次请求,交给 views.calculate_view 这个函数来处理。

提示:name='calculate' 这个参数极其重要。它为这个 URL 模式起了一个“别名”。在 HTML 模板里,你永远不应该硬编码 <a href="/calculate/">,而应该写 {% url 'calculate' %}。这样做的好处是,万一将来你把路径改成 path('compute/', ...),所有模板里的链接会自动更新,无需全局搜索替换。这是 Django “解耦”思想的典型体现。

新手常犯的一个错误是,在 path() 中写错应用名。比如,如果你的 views.py 文件不在 blog/ 目录下,而是在项目根目录,那么 from blog import views 就会报 ModuleNotFoundError。正确的做法是:确保 blog/ 是一个合法的 Django 应用(即目录下有 apps.py 和 __init__.py),并且在 settings.py 的 INSTALLED_APPS 里注册了 'blog'。你可以用 python manage.py show_urls(需安装 django-extensions)命令,实时查看当前所有已注册的 URL 映射,这是排查路由问题的终极利器。

3.2 视图函数 (views.py):数据是如何从 Python 世界“渡”到 HTML 世界的?

视图函数是整个服务端渲染流程的“心脏”。它接收一个 HttpRequest 对象(代表浏览器发来的请求),并必须返回一个 HttpResponse 对象(代表要发回给浏览器的响应)。Django 提供了 render() 这个便捷函数,它内部完成了 HttpResponse 的构造和 HTML 渲染。我们来看 calculate_view 的完整实现:

# views.py
from django.shortcuts import render
from django.http import HttpResponse
from . import calculate  # 导入同目录下的 calculate.py 模块

def calculate_view(request):
    # 1. 初始化默认上下文
    context = {
        'result': None,
        'error': None,
        'steps': []
    }

    # 2. 检查请求方法
    if request.method == 'POST':
        try:
            # 3. 从 POST 数据中提取参数
            a = float(request.POST.get('a', '0'))
            b = float(request.POST.get('b', '0'))
            operation = request.POST.get('operation', 'add')

            # 4. 调用计算模块
            if operation == 'add':
                result = calculate.add(a, b)
                steps = [f"{a} + {b} = {result}"]
            elif operation == 'multiply':
                result = calculate.multiply(a, b)
                steps = [f"{a} × {b} = {result}"]
            else:
                raise ValueError("Unsupported operation")

            # 5. 更新上下文
            context.update({
                'result': result,
                'steps': steps,
                'a': a,
                'b': b,
                'operation': operation
            })

        except (ValueError, TypeError) as e:
            context['error'] = f"计算错误:{str(e)}"

    # 6. 渲染模板并返回响应
    return render(request, 'result.html', context)

这段代码的精妙之处在于它的“防御性编程”设计。它没有假设用户一定会输入数字,而是用 try...except 包裹所有可能出错的环节。request.POST.get('a', '0') 这行代码,get() 方法的第二个参数 '0' 是默认值,意味着如果表单里根本没有 a 这个字段,就用字符串 '0' 代替,避免 KeyError。紧接着的 float() 转换,如果用户输入了 "abc",就会触发 ValueError,被 except 捕获,并把友好的错误信息放进 context['error'],最终在 result.html 里用 {% if error %}<div class="error">{{ error }}</div>{% endif %} 显示出来。

注意:render() 函数的第三个参数 context 必须是一个字典(dict)。Django 模板引擎会把这个字典的 key 当作变量名,value 当作变量值。所以你在模板里写 {{ result }},Django 就会去 context 字典里找 key 为 'result' 的值。如果 context 里没有这个 key,模板引擎会静默地渲染为空字符串,而不会报错——这是一个非常重要的特性,也是新手调试时容易忽略的点:如果你发现 {{ result }} 没显示,第一反应不应该是“模板写错了”,而应该是“views.py 里有没有把 result 放进 context 字典?”

3.3 计算模块 (calculate.py):业务逻辑为何要“隔离”?

calculate.py 是这个项目里最“干净”的文件,它不依赖 Django 的任何东西,就是一个纯粹的 Python 模块:

# calculate.py
def add(a: float, b: float) -> float:
    """执行加法运算"""
    return a + b

def multiply(a: float, b: float) -> float:
    """执行乘法运算"""
    return a * b

def is_positive(number: float) -> bool:
    """判断数字是否为正数"""
    return number > 0

将业务逻辑抽离到独立模块,有三大不可替代的好处:

  1. 可测试性(Testability):你可以完全脱离 Django 环境,用标准的 unittest 或 pytest 来测试这些函数。例如:
    ```python
    # test_calculate.py
    import unittest
    from calculate import add, multiply

    class TestCalculate(unittest.TestCase):
    def test_add(self):
    self.assertEqual(add(2, 3), 5)
    self.assertEqual(add(-1, 1), 0)

    def test_multiply(self):
        self.assertEqual(multiply(4, 5), 20)
    

    `` 运行python -m unittest test_calculate.py`,就能快速验证核心业务逻辑的正确性,而无需启动整个 Django 服务。

  2. 可替换性(Replaceability):假如某天,老板说“我们要把本地计算换成调用阿里云的数学 API”,你只需要重写 calculate.py 里的函数,把 return a + b 换成 requests.post('https://api.aliyun.com/math', json={'a': a, 'b': b}),views.py 和 templates/ 一行代码都不用改。这就是“关注点分离”的威力。

  3. 可读性(Readability):当 views.py 里充斥着 a + b、a * b 这样的表达式时,业务意图是模糊的。而 calculate.add(a, b) 这一行,清晰地表达了“我要执行一个加法操作”,语义明确,团队协作时一目了然。

3.4 HTML 模板 (hello.html 和 result.html):Django 模板引擎的“填空游戏”

Django 模板不是 HTML,而是“带有指令的 HTML”。它有两大核心语法:变量(Variables) 和 标签(Tags)。hello.html 是一个极简的表单页面:

<!-- hello.html -->
<!DOCTYPE html>
<html>
<head>
    <title>Django 计算器</title>
</head>
<body>
    <h1>欢迎使用 Django 计算器</h1>
    <form action="{% url 'calculate' %}" method="post">
        {% csrf_token %}
        <label for="a">数字 A:</label>
        <input type="number" id="a" name="a" step="any" required><br><br>

        <label for="b">数字 B:</label>
        <input type="number" id="b" name="b" step="any" required><br><br>

        <label for="operation">运算类型:</label>
        <select id="operation" name="operation">
            <option value="add">加法 (+)</option>
            <option value="multiply">乘法 (×)</option>
        </select><br><br>

        <button type="submit">计算</button>
    </form>
</body>
</html>

这里有几个新手必知的关键点:

  • {% url 'calculate' %}:这是前面提到的 URL 别名的使用。它会动态生成 /calculate/ 这个路径,确保表单提交到正确的地址。
  • {% csrf_token %}:这是 Django 的跨站请求伪造(CSRF)保护机制。任何 POST 表单都必须包含这个标签,否则 Django 会直接拒绝请求,并返回 403 Forbidden 错误。这是安全底线,绝不能省略。
  • step="any":这个 HTML 属性允许 <input type="number"> 接受小数,否则默认只能输入整数。

result.html 则展示了模板引擎最强大的能力——动态渲染:

<!-- result.html -->
<!DOCTYPE html>
<html>
<head>
    <title>计算结果</title>
</head>
<body>
    <h1>计算结果</h1>

    <!-- 显示错误信息 -->
    {% if error %}
        <div style="color: red;">{{ error }}</div>
    {% endif %}

    <!-- 显示成功结果 -->
    {% if result is not None %}
        <p><strong>您输入的数字:</strong>A = {{ a }}, B = {{ b }}, 运算 = {{ operation }}</p>
        <p><strong>计算结果:</strong>{{ result }}</p>

        <h2>计算步骤:</h2>
        <ul>
        {% for step in steps %}
            <li>{{ step }}</li>
        {% endfor %}
        </ul>

        <!-- 条件渲染:如果结果是正数,显示鼓励信息 -->
        {% if result|add:"0" > 0 %}
            <p style="color: green;">🎉 恭喜!结果是正数!</p>
        {% endif %}
    {% endif %}

    <!-- 返回首页的链接 -->
    <p><a href="{% url 'home' %}">← 返回首页</a></p>
</body>
</html>

这段模板里,{% if %}、{% for %}、{% endif %}、{% endfor %} 是模板标签,它们控制 HTML 的结构和逻辑流;{{ error }}、{{ result }}、{{ a }} 是模板变量,它们是 views.py 传递过来的数据。特别注意 {% if result|add:"0" > 0 %} 这一行:|add:"0" 是一个过滤器(Filter),它的作用是把 result 变量强制转换为数字(因为模板里所有变量默认都是字符串),这样才能进行数值比较 > 0。如果不加这个过滤器,"5" > "0" 在字符串比较中是 True,但 "10" > "0" 也是 True,而 "2" > "10" 却是 True(因为字符串比较是按 ASCII 码,‘2’ > ‘1’),这会导致逻辑错误。这个细节,是无数新手在模板里做数值判断时踩过的深坑。

4. 实操过程与核心环节实现:从零开始搭建并运行这个项目

4.1 环境准备:三步走,告别“环境地狱”

很多新手卡在第一步:环境配不起来。这个项目的设计,就是为了让你绕过所有环境陷阱。以下是经过千百次验证的、最稳妥的三步法:

第一步:确认 Python 版本
在终端(macOS/Linux)或命令提示符(Windows)中运行:

python --version
# 或者
python3 --version

确保输出是 Python 3.8 或更高版本(推荐 3.9 或 3.10)。Django 4.x 不支持 Python 3.7 及以下版本。

第二步:创建并激活虚拟环境
虚拟环境(venv)是 Python 项目的“保险箱”,它把本项目的依赖和你电脑上其他项目的依赖完全隔离开,避免版本冲突。

# 进入项目根目录(包含 manage.py 的地方)
cd /path/to/your/project

# 创建名为 venv 的虚拟环境(Linux/macOS)
python -m venv venv

# 或者(Windows)
py -m venv venv

# 激活虚拟环境
# Linux/macOS:
source venv/bin/activate

# Windows:
venv\Scripts\activate.bat

激活成功后,你的命令行提示符前会多出 (venv) 字样,这意味着你现在所有的 pip install 操作,都只会安装到这个 venv 文件夹里,不会污染全局 Python。

第三步:安装依赖并迁移数据库

# 在已激活的虚拟环境中,安装 Django
pip install django

# (可选)安装 django-extensions,用于调试
pip install django-extensions

# 运行数据库迁移(初始化 SQLite 数据库)
python manage.py migrate

# 创建一个超级管理员账号(用于访问 /admin/)
python manage.py createsuperuser
# 按照提示输入用户名、邮箱、密码

提示:python manage.py migrate 这条命令,会读取 migrations/ 目录下的 .py 文件(如 0001_initial.py),这些文件是 Django 根据 models.py 自动生成的“数据库变更脚本”。即使 models.py 是空的,Django 也会为你创建一些内置的表(如 auth_user, django_admin_log),这是 Admin 后台正常工作的基础。所以,migrate 是每次部署新环境时的必做步骤,绝不能跳过。

4.2 启动开发服务器与首次访问

一切就绪后,启动 Django 自带的开发服务器:

python manage.py runserver

你会看到类似这样的输出:

Watching for file changes with StatReloader
Performing system checks...

System check identified no issues (0 silenced).
April 05, 2024 - 10:23:45
Django version 4.2.7, using settings 'YlStlHXlVGKckUsdfZ74-master-fb7fafc9bc04a41cf60fe44ef5c03c5d72473bf0.settings'
Starting development server at http://127.0.0.1:8000/
Quit the server with CONTROL-C.

现在,打开你的浏览器,访问 http://127.0.0.1:8000/。你应该能看到 hello.html 渲染出的“欢迎使用 Django 计算器”页面。恭喜,你的第一个 Django 服务端渲染应用,已经成功跑起来了!

4.3 关键配置文件详解:settings.py 里的“开关”

settings.py 是 Django 项目的“大脑”,它控制着一切行为。对于新手,只需要关注以下几个核心配置项:

# settings.py
DEBUG = True  # 开发模式开关。设为 True 时,出错会显示详细的调试页面;上线必须设为 False!
ALLOWED_HOSTS = ['127.0.0.1', 'localhost']  # 允许访问的域名列表。开发时填本地地址;上线时必须填你的域名,如 ['myapp.com']

# 模板配置:告诉 Django 到哪里去找 .html 文件
TEMPLATES = [
    {
        'BACKEND': 'django.template.backends.django.DjangoTemplates',
        'DIRS': [BASE_DIR / 'templates'],  # 关键!这里指定了 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',
            ],
        },
    },
]

# 静态文件配置(本项目未使用,但必须存在)
STATIC_URL = '/static/'
# STATICFILES_DIRS = [BASE_DIR / 'static']  # 如果你以后要加 CSS/JS,就取消这行注释

其中,'DIRS': [BASE_DIR / 'templates'] 这一行是重中之重。它告诉 Django:“请去项目根目录下的 templates 文件夹里,寻找所有 .html 文件。” 如果你把 hello.html 错误地放在了 blog/templates/ 下,而没有在 DIRS 里添加 BASE_DIR / 'blog/templates',那么 Django 就会报错 TemplateDoesNotExist。这是新手最常见的模板找不到错误,根源几乎都在这里。

4.4 项目结构实战演练:动手修改,加深理解

光看是学不会的,必须动手改。下面是一个循序渐进的实战练习,每一步都对应一个核心概念:

练习一:修改首页标题
- 打开 templates/hello.html
- 找到 <h1>欢迎使用 Django 计算器</h1>
- 把它改成 <h1>我的第一个 Django 应用</h1>
- 保存文件,刷新浏览器 http://127.0.0.1:8000/,观察变化。体会:HTML 模板的修改是即时生效的,无需重启服务器。

练习二:增加一个“减法”选项
- 打开 calculate.py,添加一个新函数:
python def subtract(a: float, b: float) -> float: return a - b
- 打开 views.py,在 calculate_view 函数的 if operation == 'add': 分支后面,添加:
python elif operation == 'subtract': result = calculate.subtract(a, b) steps = [f"{a} - {b} = {result}"]
- 打开 templates/hello.html,在 <select> 标签里,添加一个新的 <option>:
html <option value="subtract">减法 (-)</option>
- 保存所有文件,刷新首页,选择“减法”并计算。体会:业务逻辑、视图、模板三者的联动关系。

练习三:让结果页面显示“计算时间”
- 打开 views.py,在 calculate_view 函数的 if request.method == 'POST': 块内,context.update({ 之前,添加:
python import datetime calculation_time = datetime.datetime.now().strftime("%Y-%m-%d %H:%M:%S")
- 然后在 context.update({ 里加入 'calculation_time': calculation_time,
- 打开 templates/result.html,在 <p><strong>计算结果:</strong>{{ result }}</p> 后面,添加:
html <p><strong>计算时间:</strong>{{ calculation_time }}</p>
- 保存,刷新测试。体会:Python 的标准库如何无缝注入到模板中。

5. 常见问题与排查技巧实录:那些年,我们踩过的“坑”

5.1 经典报错速查表

报错信息最可能的原因排查与解决步骤
ModuleNotFoundError: No module named 'blog'INSTALLED_APPS 里没注册 blog,或 blog/ 目录下缺少 apps.py 或 __init__.py1. 检查 settings.py 的 INSTALLED_APPS 是否包含 'blog'。
2. 检查 blog/ 目录是否存在,且包含 __init__.py(可以是空文件)。
TemplateDoesNotExist at /Django 找不到 hello.html1. 检查 settings.py 的 TEMPLATES 配置中 'DIRS' 是否指向了正确的 templates 路径。
2. 检查 templates/ 目录是否在项目根目录下,且 hello.html 文件名拼写正确(大小写敏感!)。
Reverse for 'calculate' not found.urls.py 里没有定义 name='calculate' 的路径,或 name 拼写错误1. 检查 urls.py 中 path(..., name='calculate') 的 name 参数。
2. 检查模板里 {% url 'calculate' %} 的字符串是否与 name 完全一致。
CSRF verification failed. Request aborted.表单里遗漏了 {% csrf_token %} 标签1. 打开 hello.html,确认 <form> 标签内部,<input> 标签之前,有 {% csrf_token %}。
2. 确保 settings.py 中 MIDDLEWARE 列表里包含 'django.middleware.csrf.CsrfViewMiddleware'(默认就有)。
OperationalError at /calculate/ no such table: blog_calculationhistory试图访问一个数据库表,但该表尚未通过 migrate 创建1. 运行 python manage.py showmigrations,查看哪些迁移未应用。
2. 运行 python manage.py migrate 执行所有未应用的迁移。

5.2 实操心得:那些文档里不会写的“潜规则”

心得一:“manage.py 是你的瑞士军刀,不是摆设”
新手往往只记得 runserver,却忽略了 manage.py 的其他强大功能。以下三个命令,能帮你省下 80% 的调试时间:
- python manage.py show_urls:列出所有已注册的 URL 及其对应的视图函数。当你不确定某个 URL 到底映射到哪个函数时,这是最快的验证方式。
- python manage.py shell:进入 Django 的交互式 Python shell。在这里,你可以直接导入 views、calculate,手动调用函数,测试逻辑,就像在 Jupyter Notebook 里一样。>>> from blog import calculate; print(calculate.add(1, 2))。
- python manage.py dbshell:直接进入 SQLite 数据库命令行。你可以用 SELECT * FROM auth_user; 查看管理员账号是否创建成功,用 .tables 查看所有表名。这是验证数据库状态的最直接手段。

心得二:“DEBUG=True 是你的朋友,但不是永远的朋友”
开发时,DEBUG=True 能让你看到漂亮的、带源码高亮的错误页面,上面有详细的 Traceback 和变量值。但一旦项目要上线,必须将 DEBUG=False。否则,攻击者可以通过这个页面,看到你的 settings.py 里的数据库密码、密钥等敏感信息。而且,DEBUG=False 时,Django 不会自动提供静态文件服务,你需要额外配置 STATIC_ROOT 和 collectstatic 命令,这是生产环境部署的必经之路。

心得三:“__pycache__ 和 .idea 不是垃圾,是你的‘历史记录’”
.idea 是 PyCharm 的项目配置文件夹,__pycache__ 是 Python 编译 .py 文件后生成的字节码缓存。它们不会影响程序运行,但删除它们也不会造成任何损失。.gitignore 文件里已经把它们列进去了,这意味着你 git push 的时候,它们不会上传到 GitHub。所以,放心地让它们存在吧,它们是你开发过程的“无害副产品”。

心得四:“不要迷信‘一键部署’,先学会‘手动部署’”
网上有很多 Docker Compose 一键部署 Django 的教程。但对于新手,我强烈建议你先跳过 Docker,用最原始的方式部署到一台 VPS 上:安装 Python、创建 venv、pip install django、cp 项目文件、python manage.py collectstatic、用 gunicorn 启动服务、用 nginx 做反向代理。这个过程虽然繁琐,但它会让你彻底理解 Django 应用在服务器上究竟是如何“呼吸”的。当你亲手把 gunicorn.sock 文件的权限从 777 改成 644,并因此解决了 502 Bad Gateway 错误时,那种豁然开朗的感觉,是任何自动化脚本都无法给予的。

6. 项目扩展与进阶思考:从“能跑”到“能用”的跨越

这个项目只是一个坚实的起点,而不是终点。当你能熟练地修改 calculate.py、views.py 和 templates/ 并让它们协同工作后,下一步就是给它“添砖加瓦”,让它真正具备实用价值。以下是几个平滑、自然的进阶方向,每一个都建立在你已掌握的核心概念之上:

6.1 引入数据库:从内存计算到持久化存储

目前,所有的计算都是“一闪而过”的。如果用户想知道“我昨天算过什么?”,现在的项目无法回答。这时,models.py 就不再是占位符了。你可以这样扩展:

# models.py
from django.db import models

class CalculationHistory(models.Model):
    a = models.FloatField()
    b = models.FloatField()
    operation = models.CharField(max_length=20)
    result = models.FloatField()
    created_at = models.DateTimeField(auto_now_add=True)

    def __str__(self):
        return f"{self.a} {self.operation} {self.b} = {self.result}"

然后,在 views.py 的 calculate_view 函数里,context.update({ 之后,添加:

# 保存到数据库
CalculationHistory.objects.create(
    a=a,
    b=b,
    operation=operation,
    result=result
)

最后,运行 python manage.py makemigrations 和 python manage.py migrate,Django 就会为你创建 blog_calculationhistory 这张表。你会发现,migrations/ 目录下多了一个新的 .py 文件,这就是 Django 为你生成的“数据库变更说明书”。这个过程,完美地衔接了你已有的 migrate 知识,只是从“初始化内置表”升级到了“创建自定义表”。

6.2 添加用户认证:从“匿名计算”到“个人空间”

admin.py 文件目前是空的,但它是一个金矿。你可以把它变成一个强大的后台管理界面:

# admin.py
from django.contrib import admin
from .models import CalculationHistory

@admin.register(CalculationHistory)
class CalculationHistoryAdmin(admin.ModelAdmin):
    list_display = ('a', 'b', 'operation', 'result', 'created_at')
    list_filter = ('operation', 'created_at')
    search_fields = ('a', 'b', 'result')

然后,用你之前创建的超级管理员账号,登录 http://127.0.0.1:8000/admin/,就能看到一个功能完备的、可以增删改查所有计算历史的后台。这不需要你写一行前端代码,Django 已经为你封装好了。这就是框架的力量——它把重复的、模式化的 CRUD(创建、读取、更新、删除)工作,变成了几行 Python 代码。

6.3 集成静态资源:从“裸 HTML”到“有样式的页面”

当你的 templates/ 里开始出现大量重复的 <style> 标签时,就是该引入 static/ 目录的时候了。创建 static/css/main.css,把所有 CSS 移进去;在 settings.py 里取消 STATICFILES_DIRS 的注释;然后在 hello.html 的 <head> 里添加:

{% load static %}
<link rel="stylesheet" type="text/css" href="{% static 'css/main.css' %}">

{% load static %} 是一个模板标签,它“加载”了 Django 的静态文件处理功能;{% static 'css/main.css' %} 则会根据 STATIC_URL 配置,动态生成正确的 URL,比如 /static/css/main.css。这个过程,再次印证了 Django 的核心哲学:一切皆可配置,一切皆可抽象,但抽象的目的是为了让你更专注于业务本身,而不是底层细节。

最后再分享一个小技巧:这个项目的所有文件,包括 manage.py、settings.py、urls.py,它们的名字和位置,都不是随意定的。Django 的启动流程,是严格按照一个预设的“约定优于配置”(Convention over Configuration)路径来查找的。manage.py 是入口,它会去 settings.py 里找配置,settings.py 会去 urls.py 里找路由,urls.py 会去 views.py 里找函数…… 这套约定,是 Django 社区十年沉淀下来的最佳实践。当你有一天,看到一个陌生的 Django 项目,不需要阅读任何文档,只要扫一眼它的目录结构,就能大致猜出它的数据流向和核心逻辑——那一刻,你就真正读懂了 Django。

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

简介:一个开箱即用的Django入门项目,专注传统服务端渲染流程,不引入任何前端框架。通过简单的URL配置(urls.py)将请求分发到视图函数(views.py),视图调用calculate.py完成基础业务计算,并把结果连同上下文数据传入hello.html和.html等HTML模板,由Django内置模板引擎完成最终渲染。项目结构完整,包含标准Django应用组件:models.py定义数据模型,admin.py支持后台管理,apps.py声明应用配置,migrations目录管理数据库迁移,templates文件夹集中存放所有HTML模板,settings.py提供调试与部署相关设置,manage.py用于常规命令操作,wsgi.py和asgi.py分别适配WSGI/ASGI服务器部署。配套SQLite数据库(db.sqlite3)已初始化,虚拟环境(venv)和开发配置(.gitignore、.idea、pycache)均已就位,不影响运行。适合新手动手实践请求生命周期、URL映射、视图响应、模板变量与标签、静态资源组织等核心Web开发环节。


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

基于Django的图书管理系统:从CRUD到全栈实战项目开发指南 在Web开发领域,CRUD(增删改查)操作是构建数据驱动应用的基础,而对象关系映射(ORM)技术则极大地简化了数据库交互。Django作为Python生态中一款开箱即用的全栈Web框架,其内置的ORM、Admin后台和认证系统,为开发者提供了快速构建稳健后台管理系统的能力,技术价值在于能显著提升开发效率并保证代码质量。这类技术广泛应用于内容管理系统、企业内部工具及各类信息管理平台。本文聚焦于一个经典的实战案例——学生图书管理系统,通过Django框架深度拆解其作为全栈微缩项目的实现,涵盖从数据模型设计、基于 阅读详情

相关推荐

Web框架三支柱:MVT架构、URL路由与模板系统解析

Web框架是现代动态网站开发的基石,其核心在于将HTTP请求转化为可维护、可测试、可协作的工程实践。MVT架构(Model-View-Template)通过职责分离实现业务逻辑、数据契约与表现层的解耦;URL路由机制以语义化路径替代文件映射,支持SEO友好和反向解析;模板系统则通过受限表达式确保表现逻辑无副作用。这三大技术支柱共同构成全栈开发的底层范式,广泛应用于Django、Flask等主流框架,并支撑从个人博客到企业级SaaS系统的快速构建与持续演进。

weixin_33875839的博客 340

PocketBase与HTMX构建全栈Web应用:从原理到实践

在现代Web开发中,前后端分离架构虽然带来了灵活性,但也引入了复杂的构建流程和依赖管理。其核心原理在于通过API进行数据交互,前端负责视图渲染。这种模式的技术价值在于清晰的关注点分离,但同时也增加了开发心智负担和项目复杂度。应用场景广泛,从企业级应用到个人项目均可采用。而PocketBase与HTMX的组合提供了一种回归简单的替代方案:PocketBase作为开源的嵌入式后端,内置了实时数据库和用户认证等核心功能;HTMX则通过扩展HTML属性实现动态交互,无需编写大量JavaScript。这种架构特别适合

weixin_33851429的博客 374

FastHTML:用Python写全栈Web,告别模板、JS和构建工具

FastHTML是一种面向Python工程师的现代Web框架,它基于ASGI异步标准,融合HTMX声明式交互与Python原生HTML构造能力,将传统Web开发中割裂的后端逻辑、模板渲染和前端交互三层统一为单一Python代码流。其核心原理是通过函数化HTML标签实现类型安全的UI编程,并利用HTMX属性驱动局部刷新,从而消除手写JavaScript、模板引擎和前端构建流程的必要性。技术价值在于显著降低全栈理解成本、提升开发效率与可维护性,特别适用于管理后台、数据看板、内部工具等以表单提交、列表展示、服务端

weixin_34199405的博客 454

Django模板动态URL传参实战与优化技巧

动态URL生成是Web开发中的基础技术,通过Django模板语言与URL反向解析机制实现路由与参数的动态绑定。其核心原理是利用类型转换器验证参数格式,通过`{% url %}`标签实现服务端路由映射,既保证URL规范性又避免硬编码。在电商等高并发场景中,动态URL技术能有效支持多条件筛选、分页查询等业务需求,同时需注意防范XSS注入和解决国际化路由等工程问题。通过预生成URL、参数缓存等优化手段,可显著提升包含商品详情页等动态链接的页面渲染性能。合理的URL设计还能改善SEO效果,是构建RESTful AP

weixin_30552811的博客 332

Django框架实战:从零构建Python博客系统与开发指南

Web开发框架是构建现代网络应用的基石,它通过封装通用逻辑和提供标准化结构,帮助开发者高效实现业务需求。其核心原理在于遵循特定的设计模式(如MVC/MTV),分离数据、逻辑与展示层,从而提升代码的可维护性和团队协作效率。在众多后端框架中,Django凭借其“开箱即用”的哲学和强大的ORM系统脱颖而出,尤其适合快速开发数据驱动的复杂应用,例如内容管理系统、电商平台和企业内部工具。对于开发者而言,掌握Django不仅能应对常见的“No module named”等环境配置问题,还能通过其内置的Admin后台和清

weixin_26795617的博客 332

Django集成Okta实战:OIDC认证体系重构与避坑指南

OpenID Connect(OIDC)是现代Web应用实现安全单点登录(SSO)的核心协议,其本质是一套基于OAuth2扩展的身份认证状态机,涵盖授权码流程、PKCE防护、ID Token签名验证与用户声明(Claims)映射等关键机制。采用OIDC对接Okta等专业身份云,可替代Django原生auth模块,实现企业级身份生命周期管理、多租户权限治理与合规审计支撑。技术价值在于解耦认证(AuthN)与授权(AuthZ),让Django专注业务权限执行,而Okta承担可信身份断言。典型应用场景包括SaaS

weixin_33713503的博客 337

Django注册登录

昨日内容回顾 纯手撸简易版的web框架 HTTP协议: 规定了客户端与服务端消息传输的格式 四大特性: 1.基于TCP/IP作用于应用层的协议 2.基于请求响应 3.无状态 4.无连接 请求消息格式 请求首行 请求头(一大堆kv键值对) 请求体(post请求携带的数据) 响应消息格式 响应首行 响应头(一大堆kv键值对) 响应体(你想访问的数据资源) 响应状态码 1XX 服务端已经接收到你的数据...

weixin_43183295的博客 250

MEAN全栈开发实战:从环境搭建到端到端业务落地

MEAN架构是基于JavaScript的全栈开发范式,融合MongoDB(文档型数据库)、Express.js(轻量Web框架)、AngularJS(MVVM前端框架)与Node.js(事件驱动运行时),构成统一语言、统一异步模型、统一包管理的闭环工作流。其核心价值在于降低I/O密集型应用的开发熵值,通过无模式数据结构、声明式路由、双向绑定与非阻塞I/O,显著提升MVP验证效率。典型适用于内容管理系统、内部工具平台及实时协作类场景,尤其在数据模型高频演进、团队具备前端基础、交付周期紧迫等条件下展现出不可替代

ctpaknc9526的博客 399

Django实战:从零构建学生图书管理系统,掌握全栈开发核心

在Web开发领域,ORM(对象关系映射)是连接应用与数据库的关键技术,它通过将数据库表映射为编程语言中的对象,极大简化了数据操作。其核心原理在于抽象数据库交互,让开发者能以面向对象的方式处理数据,从而提升开发效率并降低SQL直接操作的复杂度。这一技术价值在于实现了数据层与业务逻辑的解耦,使得代码更易维护和测试。在众多应用场景中,管理系统(如CRM、ERP、图书馆系统)是ORM技术的典型用武之地,它需要高效处理用户、资源、记录等实体间的复杂关系。本文以学生图书管理系统为例,深入讲解如何利用Django框架强大

weixin_34081595的博客 359

Python视频点播网站毕业设计:Django项目架构与实现全解析

视频点播作为Web开发中的经典应用场景,融合了前后端交互、文件上传、用户认证与媒体播放等核心技术。基于Python的Django框架凭借其内置的Admin后台、ORM和认证体系,成为快速构建此类系统的理想选择。理解其项目结构、数据模型与请求链路,是掌握视频点播系统开发的关键。从浏览器发起请求到服务器返回视频流,从数据库表设计到多媒体文件存储,每一步都体现着工程化思维。无论是毕业设计还是企业级应用,视频点播系统的架构思路都能迁移到电商、内容管理等广泛领域。本文以Python视频点播网站为例,深度拆解Djang

weixin_34075268的博客 386

基于Python+Django的京东商品比价系统:从爬虫到Web应用的全栈实践

网络爬虫作为自动化数据采集的核心技术,其原理在于模拟浏览器行为,向目标网站发送HTTP请求并解析返回的HTML文档,从而高效提取结构化信息。这项技术在现代数据驱动决策中价值显著,尤其在电商领域,通过实时抓取商品价格、库存及评价数据,为消费者提供精准的比价服务,辅助其做出更经济的购物选择。Django框架以其“开箱即用”的特性,为快速构建此类数据驱动的Web应用提供了强大支持,其内置的ORM、Admin后台和MTV模式,极大地简化了从数据处理到前端展示的开发流程。本系统正是这一技术组合的典型应用,它利用Pyt

weixin_30460489的博客 372

基于Django的二手交易系统:毕业设计实战与部署指南

Web开发是构建现代互联网应用的核心技术,其原理基于客户端-服务器架构,通过HTTP协议进行数据交互。Django作为Python领域的高效Web框架,采用MTV模式,通过ORM抽象数据库操作,极大地提升了开发效率与代码可维护性。其技术价值在于为快速构建功能完备、安全可靠的数据驱动型应用提供了坚实基础,广泛应用于内容管理系统、电子商务平台及企业级后台。本文聚焦于一个典型的应用场景——二手物品交易平台,详细阐述了如何利用Django框架,结合MySQL数据库与Bootstrap前端,从零部署一个具备用户管理、

weixin_33985679的博客 382

Django+Vue双端协同的电商系统实战资源(含可运行源码、部署指南与操作视频)

基于Python Django构建后端服务,MySQL管理用户、商品和订单数据;前端使用Vue.js实现响应式购物界面,完整覆盖商品展示、关键词搜索、购物车管理、订单提交与支付流程;内置后台统计模块,实时呈现平台总销量及近12个月销售趋势图表;资源包内含Django服务端与Vue客户端独立源码目录、shopping.sql数据库初始化脚本、详细部署文档(涵盖Node.js与Python环境配置、Vue项目安装与启动、Django迁移与运行步骤)、全流程操作演示视频(含前后端交互演示)、以及基础使用说明文本;

ujm567890的博客 382

django

昨日内容回顾 纯手撸简易版的web框架 HTTP协议: 规定了客户端与服务端消息传输的格式 四大特性: 1.基于tcp/ip协议,作用于应用层的协议 2.基于请求响应 3.无状态 4.无连接 请求消息格式 请求手首行 请求头(一大堆kv键值对) 请求体(post请求携带的数据) 响应消息格式 响应手首行 响应头(一大堆kv键值对) 响应体(post请求携带的数据) 响应状态码 1x...

weixin_30730151的博客 135

Python Django小说网站源码全解析:模型、部署与优化

Python Django作为全栈开发框架,以MVT架构和内置ORM著称,是构建内容型网站的高效选择。在小说阅读站点场景中,借助Django的模型字段设计、外键关系与查询优化,可实现分类、章节、书架、阅读记录等核心功能,满足从学习到毕业设计的实际需求。文章深入解析一套可运行的Django小说网站源码,涵盖数据模型、核心模块实现、本地部署、生产环境配置与常见踩坑,帮助开发者快速掌握Django内容站点的完整开发链路,并为二次开发提供可扩展的基底。

weixin_33812433的博客 326

Django+Vue双端协同的电商实战项目:含购物车、支付模拟、订单流与后台管理全套源码

直接可用的电商系统开发参考项目,后端用Django搭建API服务,前端用Vue.js实现响应式商城界面,MySQL存储数据。用户端支持账号注册登录、商品分类浏览、关键词搜索、加入购物车、生成订单、模拟在线支付(含支付状态回调逻辑)、查看订单详情、提交评价、发起退货申请并跟踪处理进度。管理员后台提供商品全生命周期管理——包括分类维护、上下架操作、首页推荐位配置、退货审核、用户与订单数据列表管理,以及基础销售统计图表展示。资源包内含完整前后端分离代码:web-client目录为Vue前端工程,shopping_

w1x2y3的博客 238

Django框架之初识

前言 1. 什么是Web应用程序? 通过Web访问的应用程序,用户只需要有浏览器即可,不需要再安装其他软件 应用程序有两种模式: C/S:C/S是客户端/服务器端程序,也就是说这类程序一般独立运行 B/S:浏览器端/服务器端应用程序,一般借助IE等浏览器来运行;本质上其实也是c/s架构 Web应用程序首先是“应用程序”,又有自己独特的地方:基于Web的,典型的浏览器/服务器架构的产...

weixin_33971130的博客 113

基于Python+Django的问卷调查系统开发与部署实战

Python凭借简洁的语法和丰富的Web框架成为快速构建业务系统的首选,而Django作为其中最具代表性的全栈框架,通过MTV架构和内置ORM大幅降低了数据库建模与业务开发的复杂度。在课程设计、毕业设计及企业内部门调研等场景中,问卷调查系统是最典型的Web应用之一,其核心诉求——动态表单渲染、数据收集与统计报表,恰好是Django的强项。利用Django自带的后台管理、模型迁移和模板引擎,开发者无需搭建额外前端工程即可完成从立项到上线的全流程。本文以一份常见的“Django问卷调查系统”代码包为切入点,围绕

weixin_33912453的博客 420
上一篇: MATLAB多模型弹道仿真工具集(含5种状态方程实现)
下一篇: Win7/Win8/Win10 64位下免安装进程隐身工具,HideToolz一键隐藏指定程序
tech5
博客等级 码龄17年 52粉丝 1363原创
评论
成就一亿技术人!
拼手气红包6.0元
还能输入1000个字符  | 博主筛选后可见
 
 条评论被折叠 查看
添加红包

请填写红包祝福语或标题

个

红包个数最小为10个

元

红包金额最低5元

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

抵扣说明:

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

余额充值