【Python】基础语法入门(三十)—— Web 开发入门:用 Flask 搭建第一个网站

系列文章:Python 基础语法入门 本文目标:从零理解 Web 开发基本原理,用 Flask 搭建第一个能跑的网站,掌握路由、模板、表单、Session、静态文件、蓝图、错误处理与 gunicorn 部署,最后结合 SQLite 做一个完整待办应用。


一、从命令行到 Web

前面 29 篇文章里,我们写的程序大多是"命令行跑一下就结束"。但现实世界里,绝大多数软件都以网站 或App形态存在:用户在浏览器点一点,服务器处理完返回结果。

为什么要学 Web 开发?

  • 用户零安装:打开浏览器就能用,不用下载安装包。
  • 跨平台:一份后端,Windows / Mac / 手机浏览器都能访问。
  • 数据集中:数据存在服务器,多用户共享、随时备份。
  • Python 生态强:Django、Flask、FastAPI 让 Python 写后端非常高效。

学完本篇,你就能用 Python 写一个真正能在浏览器访问的小网站。


二、Web 基础概念

2.1 HTTP 请求与响应

Web 的核心协议是 HTTP(超文本传输协议)。一次交互就是:

复制代码
浏览器(客户端)  ------HTTP 请求------>  服务器
浏览器(客户端)  <------HTTP 响应------  服务器

一个 HTTP 请求包含:方法 、URL 、请求头 、请求体 。 一个 HTTP 响应包含:状态码 、响应头 、响应体(HTML/JSON 等)。

2.2 GET vs POST

方法 用途 参数位置 典型场景
GET 获取资源 URL 查询串 ?key=val 打开页面、搜索
POST 提交数据 请求体 登录、注册、上传
PUT 更新整体 请求体 修改资料
DELETE 删除 URL 删除记录

原则:GET 不应修改服务器数据(只读),修改用 POST。

2.3 URL 结构

复制代码
https://www.example.com:443/users/123?role=admin#section
\___/   \_______________/\_/\____/\_/ \________/ \______/
协议        域名          端口 路径  锚点  查询参数   锚点

2.4 状态码

码段 含义 常见
2xx 成功 200 OK、201 Created
3xx 重定向 301 永久、302 临时、304 缓存
4xx 客户端错误 404 找不到、403 禁止、400 参数错
5xx 服务器错误 500 内部错误、502 网关错误

HTTP 是无状态协议,服务器记不住"这个浏览器上次来过"。为了保持登录状态:

  • Cookie:服务器让浏览器在本地存一小段数据,每次请求自动带上。
  • Session:数据存在服务器端,浏览器只存一个 Session ID(通过 Cookie 传递),更安全。

三、Flask 简介

3.1 为什么选 Flask

Flask 是 Python 轻轻量级 Web 框架,核心特点:

  • 微框架:核心只做路由 + 请求响应,其他功能用扩展按需加。
  • 上手快:5 行代码就能跑起一个网站。
  • 灵活:不强制项目结构、不强制数据库、不强制 ORM。
  • 文档优秀、社区活跃、扩展丰富。

3.2 vs Django vs FastAPI

框架 风格 适合 学习曲线
Flask 微框架,灵活 小中型、原型、API 平缓
Django 全家桶,约定优于配置 中大型、内容管理 较陡
FastAPI 异步、类型注解、自动文档 高性能 API 中等

本文选 Flask:最适合入门,概念少、代码短、能快速建立 Web 直觉。


四、安装与第一个程序

4.1 安装

复制代码
pip install flask

4.2 Hello World

新建 app.py:

复制代码
from flask import Flask

app = Flask(__name__)          # 创建 Flask 应用实例

@app.route('/')                # 路由:访问根路径时执行下面函数
def hello():
    return 'Hello, World!'     # 返回字符串作为响应体

if __name__ == '__main__':
    app.run(debug=True)        # 启动开发服务器,开启调试模式

运行:

复制代码
python app.py

运行结果:

复制代码
 * Running on http://127.0.0.1:5000
 * Debug mode: on

浏览器打开 http://127.0.0.1:5000,看到 Hello, World!。

4.3 路由 route

@app.route(path, methods=[...]) 把一个 URL 绑定到一个函数(视图函数)。

复制代码
@app.route('/about')
def about():
    return '关于我们页面'

@app.route('/user/<username>')          # 动态路由
def show_user(username):
    return f'用户:{username}'

@app.route('/post/<int:post_id>')       # 指定类型转换器
def show_post(post_id):
    return f'文章编号 {post_id}'

访问:

  • /about → 关于我们页面
  • /user/张三 → 用户:张三
  • /post/42 → 文章编号 42

常用转换器:string(默认)、int、float、path(含斜杠)、uuid。

4.4 运行与 debug 模式

app.run(debug=True) 的作用:

  1. 代码修改自动重启:改完保存,服务器自动重载,不用手动停再启。
  2. 出错显示详细堆栈:浏览器直接显示错误 traceback,方便调试。

注意:debug=True 仅用于开发,生产环境务必关闭。


五、返回 HTML 模板

直接 return 字符串写 HTML 太痛苦。Flask 用 Jinja2 模板引擎,把 HTML 和数据分离。

5.1 项目结构

复制代码
myapp/
├── app.py
├── templates/        # HTML 模板放这里
│   └── index.html
└── static/           # 静态文件(CSS/JS/图片)放这里
    └── style.css

5.2 render_template

复制代码
from flask import Flask, render_template

app = Flask(__name__)

@app.route('/')
def index():
    return render_template('index.html', name='陈序员', age=18)

templates/index.html:

复制代码
<!DOCTYPE html>
<html>
<head><title>首页</title></head>
<body>
  <h1>你好,{{ name }}!</h1>
  <p>年龄:{{ age }}</p>
</body>
</html>

浏览器访问 /,看到渲染后的页面。{``{ name }} 会被替换成传入的 name 值。

5.3 Jinja2 模板语法详解

变量 :{``{ var }}

条件判断:

复制代码
{% if age >= 18 %}
  <p>已成年</p>
{% else %}
  <p>未成年</p>
{% endif %}

循环:

复制代码
<ul>
{% for item in items %}
  <li>{{ item }}</li>
{% endfor %}
</ul>

过滤器 :{``{ name | upper }} 转大写、{``{ price | round(2) }} 保留两位小数、{``{ text | truncate(10) }} 截断。

模板继承(复用布局):

base.html:

复制代码
<html>
<head><title>{% block title %}默认标题{% endblock %}</title></head>
<body>
  <nav>导航栏</nav>
  {% block content %}{% endblock %}
  <footer>页脚</footer>
</body>
</html>

index.html:

复制代码
{% extends 'base.html' %}
{% block title %}首页{% endblock %}
{% block content %}
  <h1>首页内容</h1>
{% endblock %}

include(引入片段):

复制代码
{% include 'header.html' %}

5.4 完整待办列表页面示例

app.py:

复制代码
from flask import Flask, render_template

app = Flask(__name__)

todos = ['学Python', '学Flask', '写项目']

@app.route('/todos')
def todo_list():
    return render_template('todos.html', todos=todos, title='待办列表')

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

templates/todos.html:

复制代码
<!DOCTYPE html>
<html>
<head><title>{{ title }}</title></head>
<body>
  <h1>{{ title }}</h1>
  <ul>
  {% for t in todos %}
    <li>{{ loop.index }}. {{ t }}</li>
  {% else %}
    <li>暂无待办</li>
  {% endfor %}
  </ul>
  <p>共 {{ todos | length }} 项</p>
</body>
</html>

访问 /todos,页面显示编号列表和总数。loop.index 是循环内置变量,表示当前是第几次循环。


六、处理表单

6.1 GET 查询参数 request.args

复制代码
from flask import Flask, request

app = Flask(__name__)

@app.route('/search')
def search():
    keyword = request.args.get('q', '')    # 从查询串取 q,默认空串
    page = request.args.get('p', 1, type=int)
    return f'搜索关键词:{keyword},第 {page} 页'

访问 /search?q=flask&p=2 → 搜索关键词:flask,第 2 页。

6.2 POST 表单数据 request.form

复制代码
from flask import Flask, request, render_template

app = Flask(__name__)

@app.route('/login', methods=['GET', 'POST'])
def login():
    if request.method == 'POST':
        username = request.form.get('username')
        password = request.form.get('password')
        if username == 'admin' and password == '123456':
            return f'登录成功,欢迎 {username}'
        return '用户名或密码错误'
    return render_template('login.html')

templates/login.html:

复制代码
<!DOCTYPE html>
<html>
<head><title>登录</title></head>
<body>
  <form method="post">
    <p>用户名:<input type="text" name="username"></p>
    <p>密码:<input type="password" name="password"></p>
    <button type="submit">登录</button>
  </form>
</body>
</html>

流程:GET 访问显示表单 → 填写提交 → POST 处理校验。

6.3 文件上传 request.files

复制代码
import os
from flask import Flask, request, render_template

app = Flask(__name__)
app.config['UPLOAD_FOLDER'] = 'uploads'
os.makedirs(app.config['UPLOAD_FOLDER'], exist_ok=True)

@app.route('/upload', methods=['GET', 'POST'])
def upload():
    if request.method == 'POST':
        f = request.files['file']           # 获取上传文件
        if f:
            path = os.path.join(app.config['UPLOAD_FOLDER'], f.filename)
            f.save(path)                    # 保存到磁盘
            return f'已上传:{f.filename}'
    return render_template('upload.html')

templates/upload.html:

复制代码
<form method="post" enctype="multipart/form-data">
  <input type="file" name="file">
  <button type="submit">上传</button>
</form>

注意:表单上传文件必须加 enctype="multipart/form-data"。

6.4 重定向 redirect 和 url_for

复制代码
from flask import Flask, redirect, url_for

app = Flask(__name__)

@app.route('/')
def index():
    return '首页'

@app.route('/old')
def old():
    return redirect(url_for('index'))   # 重定向到首页视图函数对应的 URL

访问 /old 会自动跳转到 /。url_for('函数名') 根据视图函数名反查 URL,比硬编码路径更安全(改路由不用改代码)。


七、静态文件

CSS、JS、图片放 static/ 目录,Flask 自动提供访问。模板里用 url_for('static', filename='...') 引用:

复制代码
<link rel="stylesheet" href="{{ url_for('static', filename='style.css') }}">
<script src="{{ url_for('static', filename='app.js') }}"></script>
<img src="{{ url_for('static', filename='logo.png') }}">

目录结构:

复制代码
myapp/
├── app.py
├── templates/
└── static/
    ├── style.css
    ├── app.js
    └── logo.png

访问 http://127.0.0.1:5000/static/style.css 即可拿到 CSS 文件。


八、Cookie 和 Session

HTTP 协议本身是无状态 的------服务器处理完一次请求就"忘记"了这次交互,下一次请求来了,服务器并不知道是不是同一个用户。这在单纯浏览网页时没问题,但涉及登录、购物车时就不行了:用户登录后翻几个页面,总不能每页都重新输密码。为此 Web 引入了两种状态保持机制:Cookie 把少量数据存在浏览器端,每次请求自动带上;Session 把数据存在服务器端,浏览器只持有一个 ID,更安全、容量更大。下面分别演示 Flask 中的用法。

复制代码
from flask import Flask, request, make_response

app = Flask(__name__)

@app.route('/setcookie')
def set_cookie():
    resp = make_response('Cookie 已设置')
    resp.set_cookie('username', 'chen', max_age=3600)   # 1小时过期
    return resp

@app.route('/getcookie')
def get_cookie():
    val = request.cookies.get('username', '未设置')
    return f'Cookie username = {val}'

8.2 Session

Session 数据存服务器,更安全。Flask 需要设置 secret_key:

复制代码
from flask import Flask, session, redirect, url_for, request

app = Flask(__name__)
app.secret_key = 'your-secret-key-change-in-prod'   # 必须设置,用于加密签名

@app.route('/login', methods=['POST'])
def login():
    session['user'] = request.form.get('username')   # 写入 session
    return redirect(url_for('profile'))

@app.route('/profile')
def profile():
    user = session.get('user')
    if not user:
        return '未登录', 401
    return f'当前用户:{user} <a href="/logout">退出</a>'

@app.route('/logout')
def logout():
    session.pop('user', None)                        # 清除 session
    return '已退出'

生产环境若多进程/多服务器,需把 Session 存到 Redis(用 flask-session 扩展),默认实现只存内存。


九、结合 SQLite 做一个完整待办应用

前面分别学了路由、模板、表单和数据库,现在把它们串起来,做一个真正"能用"的小网站:一个待办事项清单,支持添加、标记完成、删除,数据持久化在 SQLite 里,重启服务器也不丢。这个例子虽然简单,却涵盖了 Web 开发最核心的"增删改查 + 模板渲染 + 数据持久化"闭环,理解了它,做博客、做后台管理都是同样的套路。

9.1 项目结构

复制代码
todo_app/
├── app.py
└── templates/
    └── todo.html

9.2 app.py

复制代码
import sqlite3
from flask import Flask, request, render_template, redirect, url_for, g

app = Flask(__name__)
app.config['DATABASE'] = 'todo.db'

def get_db():
    if 'db' not in g:
        g.db = sqlite3.connect(app.config['DATABASE'])
        g.db.row_factory = sqlite3.Row
    return g.db

@app.teardown_appcontext
def close_db(exc):
    db = g.pop('db', None)
    if db:
        db.close()

def init_db():
    db = get_db()
    db.execute('''
    CREATE TABLE IF NOT EXISTS todos (
        id      INTEGER PRIMARY KEY AUTOINCREMENT,
        title   TEXT NOT NULL,
        done    INTEGER DEFAULT 0
    )
    ''')
    db.commit()

@app.route('/')
def index():
    db = get_db()
    todos = db.execute("SELECT * FROM todos ORDER BY id DESC").fetchall()
    return render_template('todo.html', todos=todos)

@app.route('/add', methods=['POST'])
def add():
    title = request.form.get('title', '').strip()
    if title:
        db = get_db()
        db.execute("INSERT INTO todos (title) VALUES (?)", (title,))
        db.commit()
    return redirect(url_for('index'))

@app.route('/toggle/<int:tid>')
def toggle(tid):
    db = get_db()
    db.execute("UPDATE todos SET done = 1 - done WHERE id = ?", (tid,))
    db.commit()
    return redirect(url_for('index'))

@app.route('/delete/<int:tid>')
def delete(tid):
    db = get_db()
    db.execute("DELETE FROM todos WHERE id = ?", (tid,))
    db.commit()
    return redirect(url_for('index'))

with app.app_context():
    init_db()

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

9.3 templates/todo.html

复制代码
<!DOCTYPE html>
<html>
<head>
  <meta charset="utf-8">
  <title>待办清单</title>
  <style>
    body { font-family: sans-serif; max-width: 500px; margin: 40px auto; }
    .done { text-decoration: line-through; color: gray; }
    li { margin: 6px 0; }
  </style>
</head>
<body>
  <h1>📝 待办清单</h1>
  <form method="post" action="/add">
    <input type="text" name="title" placeholder="输入待办事项" required>
    <button type="submit">添加</button>
  </form>
  <ul>
  {% for t in todos %}
    <li class="{{ 'done' if t.done else '' }}">
      {{ t.title }}
      <a href="/toggle/{{ t.id }}">{{ '取消' if t.done else '完成' }}</a>
      <a href="/delete/{{ t.id }}">删除</a>
    </li>
  {% else %}
    <li>暂无待办,添加一个吧~</li>
  {% endfor %}
  </ul>
</body>
</html>

运行 python app.py,浏览器打开 http://127.0.0.1:5000,即可添加、完成、删除待办事项,数据持久化在 todo.db。

运行效果说明:

  • 输入"学Flask"点添加 → 列表出现该条。
  • 点"完成" → 文字加删除线变灰。
  • 点"删除" → 该条消失。
  • 重启服务器 → 数据仍在(已存 SQLite)。

十、错误处理

10.1 自定义 404 页面

复制代码
from flask import Flask, render_template

app = Flask(__name__)

@app.errorhandler(404)
def not_found(e):
    return render_template('404.html'), 404

@app.errorhandler(500)
def server_error(e):
    return '服务器内部错误,请稍后再试', 500

templates/404.html:

复制代码
<!DOCTYPE html>
<html>
<head><title>页面不存在</title></head>
<body>
  <h1>404 😕</h1>
  <p>你访问的页面不存在。</p>
  <a href="/">回首页</a>
</body>
</html>

10.2 abort 主动抛错

复制代码
from flask import Flask, abort

app = Flask(__name__)

@app.route('/user/<int:uid>')
def user(uid):
    if uid <= 0:
        abort(400, description='用户 id 必须为正整数')
    return f'用户 {uid}'

访问 /user/-1 → 返回 400 错误。


十一、蓝图 Blueprint(项目模块化)

项目变大后,所有路由写在一个 app.py 里会臃肿。**蓝图(Blueprint)**把路由按模块拆分,是 Flask 项目模块化的核心手段,相当于 Django 里的"app"概念。

11.1 为什么要用蓝图

小型项目一个文件够用,但当功能增多(用户认证、博客文章、后台管理、API 接口),全堆在 app.py 里会有几个问题:

  • 文件几千行,难以维护。
  • 多人协作容易冲突。
  • 路由命名难管理,URL 前缀容易写错。

蓝图把一组相关路由封装成独立模块,注册时统一加 URL 前缀,结构清晰、便于团队分工。

11.2 目录结构

复制代码
myapp/
├── app.py
├── auth.py
└── blog.py

auth.py:

复制代码
from flask import Blueprint

bp = Blueprint('auth', __name__, url_prefix='/auth')   # 该蓝图下所有路由加 /auth 前缀

@bp.route('/login')
def login():
    return '登录页'

@bp.route('/logout')
def logout():
    return '退出'

app.py:

复制代码
from flask import Flask
from auth import bp as auth_bp

app = Flask(__name__)
app.register_blueprint(auth_bp)     # 注册蓝图

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

访问 /auth/login、/auth/logout 即可。蓝图让大型项目结构清晰、便于团队协作。

11.3 蓝图里访问应用配置

蓝图内部可以通过 current_app 访问主应用,避免循环导入:

复制代码
from flask import Blueprint, current_app

bp = Blueprint('api', __name__, url_prefix='/api')

@bp.route('/config')
def show_config():
    # 读取主应用的配置,而不是直接 import app
    return str(current_app.config.get('API_KEY', '未设置'))

蓝图是中大型 Flask 项目的标配,建议从第二个项目起就养成用蓝图的习惯。


十三、部署:用 gunicorn 部署到生产

Flask 自带的开发服务器不能用于生产 (单线程、性能差)。生产用 gunicorn (Linux/macOS)或 uWSGI。

13.1 安装

复制代码
pip install gunicorn

13.2 启动

假设 app.py 里应用实例叫 app:

复制代码
gunicorn -w 4 -b 0.0.0.0:8000 app:app

参数说明:

  • -w 4:4 个 worker 进程(建议 CPU 核数 × 2 + 1)。
  • -b 0.0.0.0:8000:监听所有网卡的 8000 端口。
  • app:app:app.py 文件里的 app 对象。

运行结果:

复制代码
[2023-08-15 10:00:00] [INFO] Starting gunicorn 21.0
[2023-08-15 10:00:00] [INFO] Listening at: http://0.0.0.0:8000
[2023-08-15 10:00:00] [INFO] Booting worker with pid: 12345

浏览器访问 http://服务器IP:8000 即可。

13.3 常用搭配

  • Nginx:放前面做反向代理、静态文件、HTTPS。
  • systemd / supervisor:守护进程,崩溃自动重启。
  • Docker:容器化部署,环境一致。

生产典型架构:

复制代码
用户 → Nginx → gunicorn (Flask) → SQLite/MySQL

十四、配置管理与扩展生态

14.1 配置分离

实际项目里,开发用 SQLite、生产用 MySQL,密钥也不同。把配置写死在代码里是大忌,一旦上线就会暴露密钥或连错数据库。Flask 支持用配置类分离环境:

复制代码
class Config:
    SECRET_KEY = 'dev-secret'

class DevelopmentConfig(Config):
    DEBUG = True
    DATABASE = 'dev.db'

class ProductionConfig(Config):
    DEBUG = False
    DATABASE = 'prod.db'

app = Flask(__name__)
app.config.from_object(DevelopmentConfig)   # 切换环境只改这一行

print(app.config['DEBUG'])    # True

更安全的做法是从环境变量读取敏感信息,避免写进代码仓库:

复制代码
import os
app.config['SECRET_KEY'] = os.environ.get('SECRET_KEY', 'default')

14.2 常用 Flask 扩展

Flask 核心精简,复杂功能靠扩展按需引入,这是它"微框架"哲学的体现:

扩展 作用
Flask-SQLAlchemy ORM 集成
Flask-WTF 表单处理 + CSRF 防护
Flask-Login 用户登录状态管理
Flask-Migrate 数据库迁移(类似 Django migrate)
Flask-RESTful 快速构建 REST API
Flask-Caching 缓存
Flask-Mail 发邮件

安装示例:

复制代码
pip install flask-sqlalchemy flask-wtf flask-login

扩展生态是 Flask 的核心竞争力:核心保持轻量,功能随用随装,不会一开始就背一堆用不上的东西。

14.3 应用工厂模式

中大型项目推荐用工厂函数创建 app,便于测试和多实例部署:

复制代码
from flask import Flask

def create_app(config_name='development'):
    app = Flask(__name__)
    app.config.from_object(f'app.config.{config_name}Config')

    # 注册蓝图
    from app.auth import bp as auth_bp
    app.register_blueprint(auth_bp)

    return app

# run.py
app = create_app('production')

这样不同环境创建不同配置的 app,测试时也能轻松造一个独立实例,互不干扰。


十五、最佳实践

  1. 生产关闭 debug :app.run(debug=False),或直接用 gunicorn。
  2. 密钥保密 :secret_key 从环境变量读取,不要硬编码进代码。
  3. 配置分离 :开发/生产配置用 app.config.from_object() 切换。
  4. 用蓝图拆模块:项目一大就分 Blueprint。
  5. 数据库连接用 g + teardown_appcontext:请求级连接,自动关闭。
  6. 表单校验 :复杂表单用 flask-wtf 扩展,自带 CSRF 防护。
  7. 永远参数化 SQL:防 SQL 注入(见上一篇)。
  8. 静态文件生产交 Nginx:Flask 不擅长处理静态文件。
  9. 日志记录 :用 app.logger 记录请求和错误,便于排查。
  10. HTTPS:生产必须上 HTTPS,用 Nginx + Let's Encrypt 免费证书。

十六、小结

至此,Flask Web 开发入门的核心内容已全部讲完。本文从"为什么要学 Web"讲起,介绍了 HTTP、GET/POST、状态码、Cookie/Session 等 Web 基础;然后带大家用 Flask 一步步搭起一个真实网站:

  • 第一个程序:5 行 Hello World 跑起来。
  • 路由与动态参数 :@app.route、<int:id> 转换器。
  • 模板 Jinja2:变量、条件、循环、过滤器、继承、include。
  • 表单处理 :request.args / request.form / request.files、redirect + url_for。
  • 静态文件 :static/ 目录。
  • Cookie 与 Session:保持登录状态。
  • 完整待办应用:Flask + SQLite + 模板,能增删改查并持久化。
  • 错误处理 :errorhandler、abort。
  • 蓝图 Blueprint:项目模块化。
  • gunicorn 部署:生产环境正确姿势。

核心心法:Flask 把"URL → 函数 → 响应"这条链路做到极简,理解了它就理解了 Web 后端的本质。 后续可继续学 Django(全家桶)、FastAPI(异步高性能)、Flask 扩展(数据库、登录、表单)等进阶方向。

至此,Python 基础语法入门系列的核心主题已覆盖:从变量、流程控制、函数、类,到文件、异常、模块、迭代器、装饰器,再到本系列的数据库、正则、Web 开发。希望这个系列能帮你打下扎实的 Python 地基,接下来就可以向数据分析、自动化、爬虫、机器学习等方向自由进发了!


作者:全栈陈序员 系列:Python 基础语法入门 专栏:Python 从零到一 如果对你有帮助,欢迎点赞、收藏、关注 ❤️

相关推荐
全栈陈序员1 小时前
【Python】基础语法入门(三十三)—— 日志系统详解:用 logging 记录程序运行
java·开发语言·python
万少1 小时前
Harmony 7.0 这个skill帮你自动化操作AGC
前端·javascript·后端
晗夜未央1 小时前
跨仓库 Skill 换台电脑就失效?用 Git remote 校验项目
人工智能·git·python
小大宇1 小时前
Vue知识点-ElementPlus-02图标
前端·javascript·vue.js
Zack_Liu1 小时前
code样例
pytorch·python·深度学习
简简单单就是我_hehe1 小时前
一次 ClickHouse 服务器磁盘告警的排查与修复实录
java·服务器·前端
wusam1 小时前
基于HCL的python脚本编程(4)
网络·python·智能路由器
treasure1401 小时前
Django复习笔记(2026年10月)
后端·python·django·api·web·drf