北屋教程网

专注编程知识分享,从入门到精通的编程学习平台

Python教程(三十三):Web开发基础(python web开发基础教程(django)版pdf)

今日目标

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应用。

控制面板
您好,欢迎到访网站!
  查看权限
网站分类
最新留言