百度360必应搜狗淘宝本站头条
当前位置:网站首页 > 技术资源 > 正文

Python教程(三十三):Web开发基础_python进行web开发

off999 2025-09-01 11:22 8 浏览 0 评论

今日目标

o 理解Web开发的基本概念

o 掌握Flask框架的使用

o 学会创建路由和视图函数

o 了解模板渲染和表单处理

o 掌握Flask应用的基本结构

Web开发概述

Web开发是创建网站和Web应用程序的过程:

o 前端:用户界面(HTML、CSS、JavaScript)

o 后端:服务器端逻辑(Python、数据库)

o HTTP协议:客户端和服务器之间的通信协议

o Web框架:简化Web开发的工具集

Web应用的基本流程

# 简化的Web应用流程
def web_application_flow():
    """
    1. 客户端发送HTTP请求
    2. 服务器接收请求
    3. 路由系统找到对应的处理函数
    4. 处理函数执行业务逻辑
    5. 返回HTTP响应(HTML、JSON等)
    """
    pass

Flask框架介绍

Flask是一个轻量级的Python Web框架,具有以下特点:

o 微框架:核心简单,易于扩展

o 灵活性:不强制特定的项目结构

o 易学易用:学习曲线平缓

o 丰富的扩展:支持各种功能扩展

安装Flask

pip install flask

Flask基础

1. 第一个Flask应用

from flask import Flask

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

# 定义路由和视图函数
@app.route('/')
def hello_world():
    return 'Hello, World!'

@app.route('/about')
def about():
    return '这是关于页面'

@app.route('/user/<username>')
def show_user_profile(username):
    return f'用户: {username}'

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

2. 路由系统

from flask import Flask, request

app = Flask(__name__)

# 基本路由
@app.route('/')
def index():
    return '首页'

# 带参数的路由
@app.route('/user/<username>')
def user_profile(username):
    return f'用户资料: {username}'

# 指定参数类型
@app.route('/post/<int:post_id>')
def show_post(post_id):
    return f'文章ID: {post_id} (类型: {type(post_id)})'

# 多个参数
@app.route('/user/<username>/posts/<int:post_id>')
def user_post(username, post_id):
    return f'用户 {username} 的文章 {post_id}'

# HTTP方法
@app.route('/login', methods=['GET', 'POST'])
def login():
    if request.method == 'POST':
        return '处理登录请求'
    else:
        return '显示登录表单'

# 默认值
@app.route('/page/')
@app.route('/page/<int:page_num>')
def show_page(page_num=1):
    return f'显示第 {page_num} 页'

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

3. 请求和响应

from flask import Flask, request, jsonify, make_response

app = Flask(__name__)

@app.route('/api/data', methods=['GET', 'POST'])
def handle_data():
    if request.method == 'GET':
        # 获取查询参数
        name = request.args.get('name', '默认名称')
        age = request.args.get('age', 0, type=int)
        
        # 返回JSON响应
        return jsonify({
            'name': name,
            'age': age,
            'message': 'GET请求成功'
        })
    
    elif request.method == 'POST':
        # 获取表单数据
        form_data = request.form
        name = form_data.get('name', '')
        email = form_data.get('email', '')
        
        # 获取JSON数据
        json_data = request.get_json()
        
        # 获取文件
        file = request.files.get('file')
        
        return jsonify({
            'form_data': dict(form_data),
            'json_data': json_data,
            'file_name': file.filename if file else None,
            'message': 'POST请求成功'
        })

@app.route('/custom-response')
def custom_response():
    # 创建自定义响应
    response = make_response('自定义响应内容')
    response.headers['Content-Type'] = 'text/plain'
    response.headers['X-Custom-Header'] = '自定义头部'
    return response

@app.route('/redirect-example')
def redirect_example():
    # 重定向
    from flask import redirect, url_for
    return redirect(url_for('index'))

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

模板系统

1. 基本模板渲染

from flask import Flask, render_template

app = Flask(__name__)

@app.route('/')
def index():
    # 传递数据到模板
    user = {
        'name': '张三',
        'age': 25,
        'email': 'zhangsan@example.com'
    }
    
    posts = [
        {'title': '第一篇文章', 'content': '这是第一篇文章的内容'},
        {'title': '第二篇文章', 'content': '这是第二篇文章的内容'},
        {'title': '第三篇文章', 'content': '这是第三篇文章的内容'}
    ]
    
    return render_template('index.html', user=user, posts=posts)

@app.route('/user/<username>')
def user_profile(username):
    return render_template('user.html', username=username)

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

2. 模板文件示例

<!-- templates/base.html -->
<!DOCTYPE html>
<html lang="zh-CN">
<head>
    <meta charset="UTF-8">
    <meta name="viewport" content="width=device-width, initial-scale=1.0">
    <title>{% block title %}{% endblock %}</title>
    <link rel="stylesheet" href="{{ url_for('static', filename='style.css') }}">
</head>
<body>
    <header>
        <nav>
            <a href="{{ url_for('index') }}">首页</a>
            <a href="{{ url_for('about') }}">关于</a>
        </nav>
    </header>
    
    <main>
        {% block content %}{% endblock %}
    </main>
    
    <footer>
        <p>(c) 2024 Flask应用</p>
    </footer>
</body>
</html>
<!-- templates/index.html -->
{% extends "base.html" %}

{% block title %}首页{% endblock %}

{% block content %}
<div class="container">
    <h1>欢迎, {{ user.name }}!</h1>
    
    <div class="user-info">
        <p>年龄: {{ user.age }}</p>
        <p>邮箱: {{ user.email }}</p>
    </div>
    
    <h2>文章列表</h2>
    <div class="posts">
        {% for post in posts %}
        <article class="post">
            <h3>{{ post.title }}</h3>
            <p>{{ post.content }}</p>
        </article>
        {% endfor %}
    </div>
    
    {% if posts|length > 2 %}
    <p>共有 {{ posts|length }} 篇文章</p>
    {% endif %}
</div>
{% endblock %}
<!-- templates/user.html -->
{% extends "base.html" %}

{% block title %}{{ username }}的页面{% endblock %}

{% block content %}
<div class="container">
    <h1>{{ username }}的个人页面</h1>
    <p>这是 {{ username }} 的个人资料页面。</p>
</div>
{% endblock %}

3. 模板语法

<!-- 模板语法示例 -->
{% comment %}
    Jinja2模板语法
{% endcomment %}

<!-- 变量输出 -->
<p>{{ user.name }}</p>
<p>{{ user['age'] }}</p>

<!-- 条件语句 -->
{% if user.age >= 18 %}
    <p>成年人</p>
{% elif user.age >= 12 %}
    <p>青少年</p>
{% else %}
    <p>儿童</p>
{% endif %}

<!-- 循环语句 -->
{% for item in items %}
    <li>{{ item }}</li>
{% else %}
    <li>没有项目</li>
{% endfor %}

<!-- 过滤器 -->
<p>{{ user.name|upper }}</p>
<p>{{ user.name|length }}</p>
<p>{{ user.name|default('匿名用户') }}</p>

<!-- 宏定义 -->
{% macro input(name, value='', type='text') %}
    <input type="{{ type }}" name="{{ name }}" value="{{ value }}">
{% endmacro %}

<!-- 使用宏 -->
{{ input('username') }}
{{ input('password', type='password') }}

<!-- 包含其他模板 -->
{% include 'header.html' %}

<!-- 设置变量 -->
{% set title = '页面标题' %}
<h1>{{ title }}</h1>

表单处理

1. 基本表单

from flask import Flask, render_template, request, redirect, url_for, flash
from flask_wtf import FlaskForm
from wtforms import StringField, PasswordField, SubmitField
from wtforms.validators import DataRequired, Email, Length

app = Flask(__name__)
app.config['SECRET_KEY'] = 'your-secret-key-here'

# 定义表单类
class LoginForm(FlaskForm):
    username = StringField('用户名', validators=[DataRequired(), Length(min=3, max=20)])
    password = PasswordField('密码', validators=[DataRequired(), Length(min=6)])
    submit = SubmitField('登录')

class RegistrationForm(FlaskForm):
    username = StringField('用户名', validators=[DataRequired(), Length(min=3, max=20)])
    email = StringField('邮箱', validators=[DataRequired(), Email()])
    password = PasswordField('密码', validators=[DataRequired(), Length(min=6)])
    confirm_password = PasswordField('确认密码', validators=[DataRequired()])
    submit = SubmitField('注册')

@app.route('/login', methods=['GET', 'POST'])
def login():
    form = LoginForm()
    if form.validate_on_submit():
        # 处理登录逻辑
        username = form.username.data
        password = form.password.data
        
        # 这里应该验证用户名和密码
        if username == 'admin' and password == 'password':
            flash('登录成功!', 'success')
            return redirect(url_for('index'))
        else:
            flash('用户名或密码错误!', 'error')
    
    return render_template('login.html', form=form)

@app.route('/register', methods=['GET', 'POST'])
def register():
    form = RegistrationForm()
    if form.validate_on_submit():
        # 验证密码确认
        if form.password.data != form.confirm_password.data:
            flash('密码不匹配!', 'error')
            return render_template('register.html', form=form)
        
        # 处理注册逻辑
        username = form.username.data
        email = form.email.data
        password = form.password.data
        
        # 这里应该保存用户数据到数据库
        flash(f'用户 {username} 注册成功!', 'success')
        return redirect(url_for('login'))
    
    return render_template('register.html', form=form)

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

2. 表单模板

<!-- templates/login.html -->
{% extends "base.html" %}

{% block title %}登录{% endblock %}

{% block content %}
<div class="container">
    <h1>用户登录</h1>
    
    {% with messages = get_flashed_messages(with_categories=true) %}
        {% if messages %}
            {% for category, message in messages %}
                <div class="alert alert-{{ category }}">{{ message }}</div>
            {% endfor %}
        {% endif %}
    {% endwith %}
    
    <form method="POST">
        {{ form.hidden_tag() }}
        
        <div class="form-group">
            {{ form.username.label }}
            {{ form.username(class="form-control") }}
            {% if form.username.errors %}
                {% for error in form.username.errors %}
                    <span class="error">{{ error }}</span>
                {% endfor %}
            {% endif %}
        </div>
        
        <div class="form-group">
            {{ form.password.label }}
            {{ form.password(class="form-control") }}
            {% if form.password.errors %}
                {% for error in form.password.errors %}
                    <span class="error">{{ error }}</span>
                {% endfor %}
            {% endif %}
        </div>
        
        {{ form.submit(class="btn btn-primary") }}
    </form>
    
    <p>还没有账号?<a href="{{ url_for('register') }}">立即注册</a></p>
</div>
{% endblock %}

静态文件

1. 静态文件结构

your_app/
├── static/
│   ├── css/
│   │   └── style.css
│   ├── js/
│   │   └── script.js
│   └── images/
│       └── logo.png
├── templates/
│   └── ...
└── app.py

2. CSS样式示例

/* static/css/style.css */
body {
    font-family: Arial, sans-serif;
    margin: 0;
    padding: 0;
    background-color: #f4f4f4;
}

.container {
    max-width: 1200px;
    margin: 0 auto;
    padding: 20px;
}

header {
    background-color: #333;
    color: white;
    padding: 1rem;
}

nav a {
    color: white;
    text-decoration: none;
    margin-right: 20px;
}

nav a:hover {
    color: #ddd;
}

.form-group {
    margin-bottom: 15px;
}

.form-control {
    width: 100%;
    padding: 8px;
    border: 1px solid #ddd;
    border-radius: 4px;
}

.btn {
    padding: 10px 20px;
    border: none;
    border-radius: 4px;
    cursor: pointer;
}

.btn-primary {
    background-color: #007bff;
    color: white;
}

.alert {
    padding: 10px;
    margin-bottom: 15px;
    border-radius: 4px;
}

.alert-success {
    background-color: #d4edda;
    color: #155724;
    border: 1px solid #c3e6cb;
}

.alert-error {
    background-color: #f8d7da;
    color: #721c24;
    border: 1px solid #f5c6cb;
}

.post {
    background-color: white;
    padding: 15px;
    margin-bottom: 15px;
    border-radius: 4px;
    box-shadow: 0 2px 4px rgba(0,0,0,0.1);
}

错误处理

from flask import Flask, render_template

app = Flask(__name__)

@app.errorhandler(404)
def not_found_error(error):
    return render_template('404.html'), 404

@app.errorhandler(500)
def internal_error(error):
    return render_template('500.html'), 500

@app.errorhandler(403)
def forbidden_error(error):
    return render_template('403.html'), 403

# 自定义错误页面模板
<!-- templates/404.html -->
{% extends "base.html" %}

{% block title %}页面未找到{% endblock %}

{% block content %}
<div class="container">
    <h1>404 - 页面未找到</h1>
    <p>抱歉,您访问的页面不存在。</p>
    <a href="{{ url_for('index') }}">返回首页</a>
</div>
{% endblock %}

应用配置

from flask import Flask

app = Flask(__name__)

# 配置选项
app.config['SECRET_KEY'] = 'your-secret-key-here'
app.config['DEBUG'] = True
app.config['TESTING'] = False
app.config['DATABASE'] = 'path/to/database.db'

# 或者使用配置文件
class Config:
    SECRET_KEY = 'your-secret-key-here'
    DEBUG = True
    DATABASE = 'path/to/database.db'

class DevelopmentConfig(Config):
    DEBUG = True

class ProductionConfig(Config):
    DEBUG = False

# 根据环境选择配置
import os
if os.environ.get('FLASK_ENV') == 'production':
    app.config.from_object(ProductionConfig)
else:
    app.config.from_object(DevelopmentConfig)

项目结构

my_flask_app/
├── app/
│   ├── __init__.py
│   ├── models.py
│   ├── views.py
│   ├── forms.py
│   └── utils.py
├── static/
│   ├── css/
│   ├── js/
│   └── images/
├── templates/
│   ├── base.html
│   ├── index.html
│   └── user.html
├── config.py
├── requirements.txt
└── run.py

今日总结

今天我们学习了Flask Web开发的基础知识:

1. Flask框架基础:应用创建、路由系统、请求响应

2. 模板系统:Jinja2模板、模板继承、模板语法

3. 表单处理:WTForms、表单验证、CSRF保护

4. 静态文件:CSS、JavaScript、图片管理

5. 错误处理:自定义错误页面

6. 应用配置:环境配置、项目结构

Flask是一个优秀的Web开发入门框架,掌握这些基础知识可以开始构建简单的Web应用。

相关推荐

Python设计模式 第 13 章 中介者模式(Mediator Pattern)

在行为型模式中,中介者模式是解决“多对象间网状耦合”问题的核心模式。它就像“机场调度中心”——多个航班(对象)无需直接沟通起飞、降落时间,只需通过调度中心(中介者)协调,避免航班间的冲突与混乱...

1.3.1 python交互式模式的特点和用法

什么是Python交互模式Python交互模式,也叫Python交互式编程,是一种在Python解释器中运行的模式,它允许用户在解释器窗口中输入单个Python语句,并立即查看结果,而不需要编写整个程...

Python设计模式 第 8 章 装饰器模式(Decorator Pattern)

在结构型模式中,装饰器模式是实现“动态功能扩展”的核心模式。它就像“手机壳与手机的关系”——手机(原始对象)具备通话、上网等基础功能,手机壳(装饰器)可在不改变手机本身的前提下,为其新增保护、...

python设计模式 综合应用与实战指南

经过前面16章的学习,我们已系统掌握创建型模式(单例、工厂、建造者、原型)、结构型模式(适配器、桥接、组合、装饰器、外观、享元、代理)、行为型模式(责任链、命令、迭代器、中介者、观察者、状态、策略...

Python入门学习教程:第 16 章 图形用户界面(GUI)编程

16.1什么是GUI编程?图形用户界面(GraphicalUserInterface,简称GUI)是指通过窗口、按钮、菜单、文本框等可视化元素与用户交互的界面。与命令行界面(CLI)相比,...

Python 中 必须掌握的 20 个核心:str()

str()是Python中用于将对象转换为字符串表示的核心函数,它在字符串处理、输出格式化和对象序列化中扮演着关键角色。本文将全面解析str()函数的用法和特性。1.str()函数的基本用法1.1...

Python偏函数实战:用functools.partial减少50%重复代码的技巧

你是不是经常遇到这样的场景:写代码时同一个函数调用了几十次,每次都要重复传递相同的参数?比如处理文件时总要用encoding='utf-8',调用API时固定传Content-Type...

第2节.变量和数据类型【第29课-输出总结】

同学们,关于输出的知识点讲解完成之后,把重点性的知识点做一个总结回顾。·首先对于输出这一章节讲解的比如有格式化符号,格式化符号这里需要同学们额外去多留意的是不是百分号s格式化输出字符串。当然课上也说百...

AI最火语言python之json操作_python json.loads()

JSON(JavaScriptObjectNotation,JavaScript对象表示法)是一种开放标准的文件格式和数据交换格式,它易于人阅读和编写。JSON是一种常用的数据格式,比如对接各种第...

python中必须掌握的20个核心函数—split()详解

split()是Python字符串对象的方法,用于将字符串按照指定的分隔符拆分成列表。它是文本处理中最常用的函数之一。一、split()的基本用法1.1基本语法str.split(sep=None,...

实用方法分享:pdf文件分割方法 横向A3分割成纵向A4

今天在街上打印店给儿子打印试卷时,我在想:能不能,把它分割成A4在家中打印,这样就不需要跑到街上的打印店打印卷子了。原来,老师发的作业,是电子稿,pdf文件,A3格式的试卷。可是家中的打印机只能打印A...

20道常考Python面试题大总结_20道常考python面试题大总结免费

20道常考Python面试题大总结关于Python的面试经验一般来说,面试官会根据求职者在简历中填写的技术及相关细节来出面试题。一位拿了大厂技术岗SpecialOffer的网友分享了他总结的面试经...

Kotlin Data Classes 快速上手_kotlin快速入门

引言在日常开发中,我们常常需要创建一些只用来保存数据的类。问题是,这样的类往往需要写一堆模板化的方法:equals()、hashCode()、toString()……每次都重复,既枯燥又容易出错。//...

python自动化RobotFramework中Collections字典关键字使用(五)

前言介绍安装好robotframework库后,跟之前文章介绍的BuiltIn库一样BuiltIn库使用介绍,在“python安装目录\Lib\site-packages\robot\librarie...

Python中numpy数据分析库知识点总结

Python中numpy数据分析库知识点总结二、对已读取数据的处理②指定一个值,并对该值双边进行修改③指定两个值,并对第一个值的左侧和第二个值的右侧进行修改2.4数组的拼接和行列交换①竖直拼接(np...

取消回复欢迎 发表评论: