Flask入门学习记录

Flask入门练习:

Flask练习

包含的功能

  • 基础路由 :简单的 URL 与函数映射
  • 动态路由 :在 URL 中使用变量(字符串、整数等类型)
  • 自定义 URL 转换器 :实现了手机号码格式的参数验证
  • 请求参数处理 :
  • 获取查询参数(GET 请求)
  • 处理表单数据(POST 请求)
  • 文件上传功能
  • 响应处理 :
  • 返回 HTML 内容
  • 返回 JSON 数据
  • 自定义响应(状态码、响应头和 Cookie)
  • 重定向 :URL 重定向示例

在这里插入图片描述

1.app.py :主应用程序文件,包含所有路由和功能实现

# 导入必要的模块
# Flask: Web框架的核心类,用于创建应用实例
# request: 用于获取HTTP请求数据(表单数据、查询参数、文件等)
# jsonify: 将Python字典转换为JSON响应
# redirect: 用于重定向请求到其他URL
# url_for: 用于构建URL,接受视图函数名称作为参数
# make_response: 用于创建自定义响应对象
from flask import Flask, request, jsonify, redirect, url_for, render_template, make_response

# os: 提供与操作系统交互的功能,用于文件路径操作和目录创建
import os

# secure_filename: 用于安全地处理上传的文件名,防止路径遍历攻击
from werkzeug.utils import secure_filename

# BaseConverter: 用于创建自定义URL转换器的基类
from werkzeug.routing import BaseConverter

# 创建Flask应用实例
# __name__: 当前模块的名称,Flask用它来确定应用的根路径
app = Flask(__name__)

# 配置参数设置
# app.config.update(): 一次性更新多个配置项
app.config.update(
    # DEBUG: 开启调试模式,启用自动重载和详细错误页面
    # True: 开启调试模式,False: 关闭调试模式
    DEBUG=True,
    
    # SECRET_KEY: 用于会话安全的密钥,应当保密且复杂
    # 在生产环境中应使用随机生成的复杂字符串
    SECRET_KEY='your_secret_key_here',
    
    # UPLOAD_FOLDER: 文件上传的存储路径
    # os.path.dirname(os.path.abspath(__file__)): 获取当前脚本所在的目录
    # os.path.join(): 连接路径组件,确保跨平台兼容性
    UPLOAD_FOLDER=os.path.join(os.path.dirname(os.path.abspath(__file__)), 'uploads'),
    
    # ALLOWED_EXTENSIONS: 允许上传的文件类型集合
    # 这里允许上传文本文件、PDF文件和常见图片格式
    ALLOWED_EXTENSIONS={'txt', 'pdf', 'png', 'jpg', 'jpeg', 'gif'}
)

# 确保上传文件夹存在
# os.makedirs(): 创建目录,如果目录已存在则不报错
# exist_ok=True: 如果目录已存在,不会引发异常
os.makedirs(app.config['UPLOAD_FOLDER'], exist_ok=True)

# 自定义转换器 - 手机号码转换器
# 继承BaseConverter类来创建自定义URL转换器
class MobileConverter(BaseConverter):
    """自定义手机号码URL转换器
    
    用于验证URL中的参数是否符合中国大陆手机号格式
    例如: /mobile/13812345678
    """
    # 定义正则表达式模式
    # r'1[3-9]\d{9}': 匹配中国大陆手机号码格式
    # 1开头,第二位是3-9之间的数字,后面跟9个数字
    regex = r'1[3-9]\d{9}'
    
    def to_python(self, value):
        """将URL中的参数转换为Python对象
        
        参数:
            value (str): URL中捕获的字符串值
            
        返回:
            str: 处理后的值,这里直接返回原值
        """
        return value
    
    def to_url(self, value):
        """将Python对象转换为URL中的参数
        
        参数:
            value (str): 要转换为URL参数的Python对象
            
        返回:
            str: URL中使用的字符串,这里直接返回原值
        """
        return value

# 注册自定义转换器
# app.url_map.converters: 存储所有URL转换器的字典
# 'mobile': 转换器的名称,在路由中使用,如 <mobile:phone_number>
app.url_map.converters['mobile'] = MobileConverter

# 辅助函数 - 检查文件扩展名是否允许
def allowed_file(filename):
    """检查上传的文件扩展名是否在允许列表中
    
    参数:
        filename (str): 要检查的文件名
        
    返回:
        bool: 如果文件扩展名在允许列表中返回True,否则返回False
    """
    # '.' in filename: 检查文件名中是否包含点号(即是否有扩展名)
    # filename.rsplit('.', 1)[1].lower(): 获取文件扩展名并转为小写
    # rsplit('.', 1): 从右侧按点号分割,最多分割1次,返回列表
    # [1]: 获取分割后的第二部分,即扩展名
    # lower(): 将扩展名转换为小写,以便不区分大小写比较
    return '.' in filename and \
           filename.rsplit('.', 1)[1].lower() in app.config['ALLOWED_EXTENSIONS']

# 路由:首页
# @app.route(): 路由装饰器,将URL规则映射到视图函数
# '/': URL规则,这里是根路径
@app.route('/')
def index():
    """首页路由 - 返回HTML内容
    
    返回:
        str: 包含链接列表的HTML内容,展示应用的所有功能示例
    """
    # 返回一个HTML字符串,包含应用功能的链接列表
    return '''
    <h1>Flask学习示例</h1>
    <p>这是一个包含Flask基础功能的示例应用</p>
    <ul>
        <li><a href="/hello">基本路由示例</a></li>
        <li><a href="/user/admin">动态路由示例 - 字符串参数</a></li>
        <li><a href="/user/123">动态路由示例 - 整数参数</a></li>
        <li><a href="/mobile/13812345678">自定义转换器示例 - 手机号</a></li>
        <li><a href="/query?name=flask&age=10">查询参数示例</a></li>
        <li><a href="/form">表单提交示例</a></li>
        <li><a href="/upload">文件上传示例</a></li>
        <li><a href="/json">JSON响应示例</a></li>
        <li><a href="/redirect-example">重定向示例</a></li>
        <li><a href="/custom-response">自定义响应示例</a></li>
    </ul>
    '''

# 路由:基本示例
@app.route('/hello')
def hello():
    """基本路由示例 - 返回简单字符串
    
    返回:
        str: 简单的问候字符串
    """
    # 返回一个简单的字符串作为HTTP响应
    return 'Hello, Flask!'

# 路由:动态路由 - 字符串参数
# <string:username>: 动态URL部分,捕获字符串类型的参数并命名为username
@app.route('/user/<string:username>')
def show_user_profile(username):
    """动态路由示例 - 接收字符串参数
    
    参数:
        username (str): 从URL中捕获的用户名字符串
        
    返回:
        str: 包含用户名的响应字符串
    """
    # f-string格式化字符串,将捕获的参数插入到响应中
    return f'用户名: {username}'

# 路由:动态路由 - 整数参数
# <int:user_id>: 动态URL部分,捕获整数类型的参数并命名为user_id
# 如果参数不是整数,Flask会返回404错误
@app.route('/user/<int:user_id>')
def show_user_id(user_id):
    """动态路由示例 - 接收整数参数
    
    参数:
        user_id (int): 从URL中捕获的用户ID整数
        
    返回:
        str: 包含用户ID的响应字符串
    """
    # 返回包含整数参数的字符串
    return f'用户ID: {user_id}'

# 路由:自定义转换器 - 手机号
# <mobile:phone_number>: 使用自定义的mobile转换器处理URL参数
@app.route('/mobile/<mobile:phone_number>')
def show_mobile(phone_number):
    """自定义转换器示例 - 接收符合手机号格式的参数
    
    参数:
        phone_number (str): 从URL中捕获的手机号码字符串
                            必须符合中国大陆手机号格式
        
    返回:
        str: 包含手机号的响应字符串
    """
    # 返回包含手机号的字符串
    return f'手机号: {phone_number}'

# 路由:获取查询参数
@app.route('/query')
def query_params():
    """查询参数示例 - 获取URL中的查询参数
    
    URL示例: /query?name=flask&age=10
    
    返回:
        str: 包含查询参数值的响应字符串
    """
    # request.args: 包含所有查询参数的不可变字典(ImmutableMultiDict)
    # get('name', '未提供'): 获取名为'name'的参数值,如果不存在则返回默认值'未提供'
    name = request.args.get('name', '未提供')
    age = request.args.get('age', '未提供')
    
    # 返回包含查询参数的字符串
    return f'查询参数 - 姓名: {name}, 年龄: {age}'

# 路由:表单提交
# methods=['GET', 'POST']: 指定路由支持的HTTP方法
# 默认情况下,路由只响应GET请求
@app.route('/form', methods=['GET', 'POST'])
def form_example():
    """表单提交示例 - 处理GET和POST请求
    
    GET请求: 返回包含表单的HTML页面
    POST请求: 处理表单提交的数据
    
    返回:
        str: 根据请求类型返回表单页面或处理结果
    """
    # request.method: 当前请求的HTTP方法(GET、POST等)
    if request.method == 'POST':
        # 处理POST请求(表单提交)
        
        # request.form: 包含表单数据的不可变字典
        # get('username', '未提供'): 获取表单字段值,如果不存在则返回默认值
        username = request.form.get('username', '未提供')
        password = request.form.get('password', '未提供')
        
        # 返回处理结果
        return f'表单提交成功 - 用户名: {username}, 密码: {password}'
    else:
        # 处理GET请求,返回表单页面
        return '''
        <form method="post">
            <div>
                <label>用户名:</label>
                <input type="text" name="username">
            </div>
            <div>
                <label>密码:</label>
                <input type="password" name="password">
            </div>
            <button type="submit">提交</button>
        </form>
        '''

# 路由:文件上传
@app.route('/upload', methods=['GET', 'POST'])
def upload_file():
    """文件上传示例 - 处理文件上传请求
    
    GET请求: 返回文件上传表单
    POST请求: 处理上传的文件
    
    返回:
        str: 根据请求类型返回上传表单或处理结果
    """
    if request.method == 'POST':
        # 处理POST请求(文件上传)
        
        # request.files: 包含所有上传文件的不可变字典
        # 'file' not in request.files: 检查是否有名为'file'的文件字段
        if 'file' not in request.files:
            return '没有文件部分'
        
        # 获取上传的文件对象
        file = request.files['file']
        
        # 检查文件名是否为空
        # 当用户未选择文件但点击提交时,浏览器会发送一个空文件名
        if file.filename == '':
            return '未选择文件'
        
        # 检查文件是否存在且扩展名是否允许
        if file and allowed_file(file.filename):
            # secure_filename(): 确保文件名安全,防止路径遍历攻击
            # 例如将 "../../../etc/passwd" 转换为 "etc_passwd"
            filename = secure_filename(file.filename)
            
            # 构建保存路径并保存文件
            # os.path.join(): 连接路径组件,确保跨平台兼容性
            file_path = os.path.join(app.config['UPLOAD_FOLDER'], filename)
            # file.save(): 将上传的文件保存到指定路径
            file.save(file_path)
            
            # 返回成功消息
            return f'文件上传成功: {filename}'
    
    # GET请求返回上传表单
    # enctype="multipart/form-data": 必须设置此属性才能上传文件
    return '''
    <form method="post" enctype="multipart/form-data">
        <div>
            <label>选择文件:</label>
            <input type="file" name="file">
        </div>
        <button type="submit">上传</button>
    </form>
    '''

# 路由:JSON响应
@app.route('/json')
def json_example():
    """JSON响应示例 - 返回JSON格式数据
    
    返回:
        Response: 包含JSON数据的Flask响应对象
                 Content-Type自动设置为application/json
    """
    # 创建要返回的数据字典
    data = {
        'name': 'Flask示例',
        'version': '1.0',
        'features': ['路由', '请求处理', '响应', '文件上传']
    }
    
    # jsonify(): 将Python字典转换为JSON响应
    # 自动设置Content-Type为application/json
    return jsonify(data)

# 路由:重定向示例
@app.route('/redirect-example')
def redirect_example():
    """重定向示例 - 将请求重定向到另一个URL
    
    返回:
        Response: 重定向响应,默认状态码为302(临时重定向)
    """
    # redirect(): 创建重定向响应
    # url_for('index'): 生成index视图函数对应的URL
    # url_for()比硬编码URL更灵活,当路由规则改变时不需要修改代码
    return redirect(url_for('index'))

# 路由:自定义响应
@app.route('/custom-response')
def custom_response():
    """自定义响应示例 - 创建自定义HTTP响应
    
    返回:
        Response: 自定义的Flask响应对象
    """
    # make_response(): 创建响应对象
    # 参数是响应的主体内容
    response = make_response('<h1>这是一个自定义响应</h1>')
    
    # 设置响应头
    # response.headers: 响应头字典
    # Content-Type: 指定响应的MIME类型
    response.headers['Content-Type'] = 'text/html'
    # X-Custom-Header: 自定义响应头,可用于传递额外信息
    response.headers['X-Custom-Header'] = 'Flask示例'
    
    # 设置Cookie
    # set_cookie(): 在响应中设置Cookie
    # 参数1: Cookie名称
    # 参数2: Cookie值
    # 还可以设置max_age, expires, path, domain, secure, httponly等参数
    response.set_cookie('username', 'flask_user')
    
    # 设置状态码
    # status_code: 响应的HTTP状态码
    # 200: 表示请求成功
    response.status_code = 200
    
    # 返回响应对象
    return response

# 启动应用
# __name__ == '__main__': 确保只有直接运行此脚本时才执行下面的代码
# 当作为模块导入时不会执行
if __name__ == '__main__':
    # app.run(): 启动Flask内置的开发服务器
    # debug=True: 开启调试模式,启用自动重载和详细错误页面
    # host='0.0.0.0': 监听所有网络接口,允许外部访问
    # port=5000: 指定服务器端口号
    app.run(debug=True, host='0.0.0.0', port=5000)

项目结构

Flask/
├── app.py          # 主应用程序文件
├── uploads/        # 上传文件存储目录(自动创建)
└── README.md       # 项目说明文档

运行说明

环境准备

  1. 确保已安装Python(推荐3.7+)
  2. 安装Flask框架:
pip install flask

启动应用

方法一:直接运行Python文件

python app.py

方法二:使用Flask命令(Windows系统)

set FLASK_APP=app.py
flask run

方法二:使用Flask命令(Linux/Mac系统)

export FLASK_APP=app.py
flask run

访问应用

启动应用后,在浏览器中访问:

http://127.0.0.1:5000/

你将看到主页面,其中包含了所有示例功能的链接,可以点击各个链接进行测试。

学习要点

通过本项目,你可以学习以下Flask知识点:

  1. Flask应用的创建和配置
  2. 路由系统和URL规则
  3. 请求对象的使用
  4. 响应的生成和处理
  5. 文件上传的处理
  6. 自定义URL转换器

扩展学习

完成本示例后,可以尝试:

  1. 添加模板渲染(使用Jinja2)
  2. 集成数据库(如SQLAlchemy)
  3. 添加用户认证(如Flask-Login)
  4. 创建RESTful API
  5. 添加表单验证(如Flask-WTF)

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值