news 2026/10/30 7:00:32

用Python创建简易网站图文教程

作者头像

张小明

前端开发工程师

1.2k 24
文章封面图
用Python创建简易网站图文教程

前言


很多人第一次听到「用 Python 建网站」,脑子里立刻浮现出装一堆东西、配一整套环境的画面。其实从「浏览器里能看到一个页面」到「一个能点、能跳转的站」,中间的路是一段一段走出来的:标准库能带你走完第一步,真正让页面变成「站」的,是后面加上的路由、模板和静态文件组织方式。


另一个常见误解,是把「建网站」和「写 API」当成同一件事。API 面向的是程序调用方,返回的通常是 JSON;网站面向的是人,最终要吐出一整页 HTML 交给浏览器渲染。本文讲的是后者——一个有人能看的网页站点。API 的设计思路属于另一类话题,本文不展开。


本文按三步走:先用标准库http.server把页面跑起来,理解 HTTP 请求与响应这条最底层链路;再引出 WSGI 这个「服务器」与「应用」之间的接口约定,解释为什么框架可以换来换去;最后用一个轻量框架把路由、模板、静态文件三件套补齐,并讲清「服务端渲染」到底指什么。


文中涉及第三方框架的部分都需要自行安装,安装命令、版本号与具体参数一律以对应框架的官方文档为准,本文只讲结构与思路。


一、第一步:用 http.server 让浏览器看到第一行字


HTTP 协议的本质是一问一答:浏览器发来一段文本(请求),服务器回一段文本(响应)。响应由三部分组成——状态行、若干响应头、以及一个空行之后的响应体。状态行里那个200表示成功,404表示资源不存在。


标准库里的http.server模块允许我们直接写一个处理类,把响应的这三部分自己拼出来。


# 适用于 Python 3.7+
from http.server import BaseHTTPRequestHandler, HTTPServer


class HelloHandler(BaseHTTPRequestHandler):
def do_GET(self):
if self.path == "/":
body = "<h1>你好,Python 网站</h1>".encode("utf-8")
self.send_response(200)
self.send_header("Content-Type", "text/html; charset=utf-8")
self.send_header("Content-Length", str(len(body)))
self.end_headers()
self.wfile.write(body)
else:
self.send_error(404, "页面不存在")


if __name__ == "__main__":
server = HTTPServer(("127.0.0.1", 8000), HelloHandler)
print("请在浏览器打开 http://127.0.0.1:8000/")
server.serve_forever()

几个关键点:send_response(200)会先写入状态行,并把Server与Date两个响应头加进缓冲区;后面两次send_header追加自定义头;end_headers()负责写入那个表示头部结束的空行——在 3.3 之后,头部是缓冲的,不调用end_headers()响应发不出去;最后往self.wfile写响应体。


Content-Length是响应体的字节数,不是字符数。中文一个字符占 3 个字节,所以必须先encode("utf-8")再取长度,否则浏览器会等一段永远等不到的数据。


这段代码已经是一个「能访问的页面」,但它还不是「网站」:每加一个网址,就要多写一个if;页面内容硬编码在 Python 字符串里;图片、CSS 文件没地方放。


二、从「一个脚本」到「一个站」:WSGI 接口约定


如果每个网站都自己实现一套「读请求 → 拼响应」的逻辑,那么服务器(负责监听端口、解析 HTTP)和框架(负责业务逻辑)就绑死了。WSGI(Web Server Gateway Interface,Web 服务器网关接口)解决的正是这个耦合问题。


WSGI 规定了一个极其简洁的调用约定:应用是一个可调用对象,接收两个参数并返回一个可迭代对象。



  • 第一个参数是environ,一个字典,装着这次请求的全部信息,比如REQUEST_METHOD(请求方法)、PATH_INFO(路径)、QUERY_STRING(查询串)。

  • 第二个参数是start_response,应用用它来声明状态行和响应头。

  • 返回值是可迭代对象,每个元素是一段响应体的字节串。


标准库的wsgiref提供了这个接口的参考实现。下面这段代码和上一节功能相同,但遵循了 WSGI 约定。


# 适用于 Python 3.7+
from wsgiref.simple_server import make_server


def app(environ, start_response):
path = environ["PATH_INFO"]
if path == "/":
status = "200 OK"
body = "<h1>你好,Python 网站</h1>".encode("utf-8")
else:
status = "404 Not Found"
body = "<h1>页面不存在</h1>".encode("utf-8")
headers = [
("Content-Type", "text/html; charset=utf-8"),
("Content-Length", str(len(body))),
]
start_response(status, headers)
return [body]


if __name__ == "__main__":
with make_server("127.0.0.1", 8000, app) as httpd:
httpd.serve_forever()

好处是:只要遵守这个约定,任何 WSGI 服务器都能跑你的应用,任何 WSGI 应用也能跑在任何服务器上。生产环境中常见的 Gunicorn、uWSGI 这类服务器,都吃这一套接口。框架负责把业务代码包装成 WSGI 应用,服务器负责把 HTTP 翻译成environ。


不过手写if path == ...分派还是太笨。真正的框架把这部分抽象成「路由」——你把「某个路径 + 某个方法」映射到一个函数上。


三、用轻量框架补齐三件套:路由、模板、静态文件


一个网站最小可用,需要三样东西:把路径映射到处理函数(路由)、把数据和网页骨架拼起来(模板)、把 CSS/图片/JS 这类不变的资源单独提供给浏览器(静态文件)。主流轻量框架都自带这三样。下面以 Flask 为例,安装命令与接口细节请以其官方文档为准。


# 安装方式以该框架官方文档为准
pip install flask

# 适用于 Python 3.8+;需先安装 Flask
from flask import Flask, render_template

app = Flask(__name__)

POSTS = [
{"title": "第一篇", "body": "网站跑起来了。"},
{"title": "第二篇", "body": "模板也接上了。"},
]


@app.get("/")
def index():
return render_template("index.html", posts=POSTS)


@app.get("/post/<int:pid>")
def post_detail(pid):
if pid < 0 or pid >= len(POSTS):
return "没有这篇文章", 404
return render_template("post.html", post=POSTS[pid])


if __name__ == "__main__":
app.run(debug=True)

@app.get(...)是 Flask 2.0 之后的写法,等价于更早版本的@app.route("/", methods=["GET"])。路径里用尖括号声明的片段是路径参数(上面的代码里把文章编号声明成了整数),框架会自动把 URL 里对应那一段转成整数再传进函数,不用自己切字符串。


模板是一个带占位符的 HTML 文件。框架会读它、把数据填进去、生成最终 HTML:


<!-- templates/index.html -->
<!DOCTYPE html>
<html lang="zh">
<head><meta charset="utf-8"><title>我的网站</title></head>
<body>
<h1>文章列表</h1>
<ul>
{% for post in posts %}
<li><a href="/post/{{ loop.index0 }}">{{ post.title }}</a></li>
{% endfor %}
</ul>
</body>
</html>

静态文件放在框架约定的目录(Flask 默认是static/),通过固定的 URL 前缀访问:


<link rel="stylesheet" href="/static/style.css">

框架会把/static/style.css直接映射到磁盘上的static/style.css,不经过你的视图函数。这样做的好处是:模板只负责结构,CSS 只负责样式,同一个样式文件被浏览器缓存一次,全站的页面都受益。


四、服务端渲染到底是什么


上面这套流程有个名字,叫服务端渲染(SSR,Server-Side Rendering)。它的意思很直白:HTML 是在服务器上完整拼好之后,才发给浏览器的。


以访问首页为例,服务器端的动作顺序是:收到 GET 请求 → 路由匹配到index函数 → 读取POSTS数据 → 用模板把数据渲染成一段完整 HTML → 把这段 HTML 作为响应体发出。浏览器收到的已经是一张排好版的页面,它不需要再执行多少脚本就能显示内容。




对比项服务端渲染(SSR)客户端渲染(CSR)



HTML 由谁生成服务器上的模板引擎浏览器里的 JavaScript

首屏可见速度通常更快,响应即内容需等脚本下载并执行完

搜索引擎抓取直接看到完整内容依赖爬虫执行脚本的能力

服务器压力每次请求都要渲染,压力大静态资源可走缓存,压力小

典型场景内容型站点、后台管理页交互复杂的单页应用



需要注意的是,SSR 并不等于「不能用 JavaScript」。它只描述首屏 HTML 从哪来。页面加载完之后,你依然可以在浏览器里用脚本做局部更新——两种渲染方式经常混着用。


常见坑点


1. 把http.server当生产服务器


❌ 直接拿标准库的那个服务器类对外提供正式服务。 ✅ 官方文档对此有明确警告:不推荐用于生产环境,因为它只实现了最基本的安全检查。它只适合测试和临时用途,要对外就用成熟的 WSGI 生产服务器。


2. 把路由写成一路if


❌ 每加一个页面就复制一份处理函数、再补一个if path == ...分支。 ✅ 用框架的路由装饰器,把「路径 + 方法」声明式地绑到函数上,路径参数由框架解析。


3. 模板里直接写业务计算


❌ 在{% for %}里做数据库查询、算复杂统计。 ✅ 模板只管展示;数据和计算在视图函数里准备好,再作为参数传进去。


4. 静态文件的 URL 和磁盘路径混淆


❌ 以为浏览器访问/static/style.css会命中项目根目录下的static/style.css,于是在别处又放了一份。 ✅ 以框架约定的目录为准(常见约定是static/),URL 前缀是框架映射出来的虚拟路径,照约定放文件就行。


5. 中文页面不声明编码


❌ 返回中文 HTML 却不写Content-Type,浏览器按本地编码猜,出现乱码。 ✅ 响应头写text/html; charset=utf-8,HTML 里的meta charset也写一遍,两者保持一致。


6. 以为服务端渲染就不能用 JavaScript


❌ 担心「选了 SSR 就再也不能做局部更新」,于是把交互逻辑全塞到服务器。 ✅ 服务端渲染只描述首屏 HTML 从哪里来;页面加载完之后照样可以在浏览器里做局部更新,两种方式经常混用。


总结




阶段用什么你得到什么缺什么



起步http.server一个能响应的地址路由、模板、静态文件都要手写

解耦wsgiref+ WSGI 约定服务器与应用解耦业务分派仍是手写的if

成型轻量框架路由、模板、静态文件三件套需要按官方文档安装与配置



从「一个脚本」到「一个站」,本质上是把重复劳动一层层收进约定里:HTTP 的细节收进服务器,分派逻辑收进路由,页面拼接收进模板。理解 WSGI 这层接口,你就明白了为什么 Python 的 Web 框架能百花齐放却又能共用同一批服务器;理解服务端渲染,你就明白了「网站」和「API」在交付物上的根本差别。




版权声明: 本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若内容造成侵权/违法违规/事实不符,请联系邮箱:809451989@qq.com进行投诉反馈,一经查实,立即删除!
网站建设 2026/10/30 7:00:31

DeepSeek中小学生手册:四块提示词模板与避坑清单

简介&#xff1a;《DeepSeek中小学生使用手册&#xff1a;多领域学习指导与成长辅助工具》是一份面向小学至高中学生及家长的AI教育实践指南&#xff0c;旨在把自然语言处理与机器学习应用落到日常学习场景&#xff0c;缓解学习兴趣不足、学科方法缺失与家庭教育沟通不畅等问题…

作者头像 李华
网站建设 2026/10/30 7:00:22

从方差图到协方差加权:单目RGB nerf-slam稠密重建复现

简介&#xff1a;这份《nerf-slam的复现文档》面向希望入门或复现神经辐射场与同步定位建图结合方案的研究者和工程实践者&#xff0c;聚焦稠密三维重建流程。压缩包仅含1个docx文件&#xff0c;大小约11.01MB&#xff0c;以文字讲解和复现记录为主&#xff0c;便于按章节查阅、…

作者头像 李华
网站建设 2026/10/30 6:59:39

MATLAB Aerospace Toolbox飞行仿真与卫星轨道实践

简介&#xff1a;这份 MATLAB Aerospace Toolbox R2023b 官方用户手册面向航空航天工程、飞控与导航仿真方向的 MATLAB 使用者&#xff0c;包括高校学生、科研人员和工程技术人员&#xff0c;用于解决工具箱函数查询、模块调用与官方示例对照的问题。手册由 MathWorks 发布&…

作者头像 李华
网站建设 2026/10/30 6:59:06

机器学习调参救不了模型?先搞懂算法原理与数据预处理

简介&#xff1a;这份PDF面向机器学习初学者与需要系统梳理知识框架的开发者&#xff0c;围绕算法概述、原理与典型应用三条主线展开&#xff0c;帮助读者建立从概念到落地的整体认知。全文以监督学习、非监督学习、半监督学习和强化学习四大类为切入点&#xff0c;并依次讲解数…

作者头像 李华
网站建设 2026/10/30 6:58:31

PomeType 自定义词条:说「我的邮箱」就出邮箱地址,填表少打几遍

天天填表的人&#xff0c;邮箱、公司全称、统一社会信用代码这几样&#xff0c;一周要打好多遍。PomeType 的自定义词条能把它们存成口令&#xff1a;说一句短的&#xff0c;写进去的是一整段固定文字。 这篇只讲词条怎么用&#xff0c;听写本身怎么开不展开。 一、口令&#x…

作者头像 李华
网站建设 2026/10/30 6:58:19

ASP.NET WebForms影视导航源码解析与IIS复现指南

简介&#xff1a;这是一套基于ASP开发的电影视频资源站源码&#xff0c;适用于希望快速搭建影视类网站的Web开发者或个人站长&#xff0c;尤其适合熟悉ASPAccess/SQL Server技术栈的入门至中级学习者。资源包含414个文件&#xff0c;主体为89个ASP核心逻辑文件&#xff08;如Ad…

作者头像 李华