← 返回主页

第13课: Web开发基础

Flask框架入门

Flask是一个轻量级的Python Web框架,简单易学,适合快速开发Web应用。

安装Flask

pip install flask

第一个Flask应用

from flask import Flask

app = Flask(__name__)

@app.route('/')
def home():
    return "Hello, Flask!"

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

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

# 运行: python app.py
# 访问: http://localhost:5000

路由和参数

from flask import Flask

app = Flask(__name__)

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

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

# 多个路由指向同一个函数
@app.route('/home')
@app.route('/index')
def index():
    return "首页"

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

HTTP方法

from flask import Flask, request

app = Flask(__name__)

@app.route('/login', methods=['GET', 'POST'])
def login():
    if request.method == 'POST':
        username = request.form['username']
        password = request.form['password']
        return f"登录用户: {username}"
    else:
        return "显示登录表单"

# 获取查询参数
@app.route('/search')
def search():
    query = request.args.get('q', '')
    return f"搜索: {query}"

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

模板渲染

from flask import Flask, render_template

app = Flask(__name__)

@app.route('/hello/')
def hello(name):
    return render_template('hello.html', name=name)

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

创建模板文件 templates/hello.html:

<!DOCTYPE html>
<html>
<head>
    <title>Hello</title>
</head>
<body>
    <h1>Hello, {{ name }}!</h1>
    {% if name == "张三" %}
        <p>欢迎回来!</p>
    {% endif %}
</body>
</html>

JSON API

from flask import Flask, jsonify, request

app = Flask(__name__)

users = [
    {"id": 1, "name": "张三", "age": 25},
    {"id": 2, "name": "李四", "age": 30}
]

@app.route('/api/users', methods=['GET'])
def get_users():
    return jsonify(users)

@app.route('/api/users/', methods=['GET'])
def get_user(user_id):
    user = next((u for u in users if u['id'] == user_id), None)
    if user:
        return jsonify(user)
    return jsonify({"error": "用户不存在"}), 404

@app.route('/api/users', methods=['POST'])
def create_user():
    data = request.get_json()
    new_user = {
        "id": len(users) + 1,
        "name": data['name'],
        "age": data['age']
    }
    users.append(new_user)
    return jsonify(new_user), 201

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

Django框架简介

Django是一个功能完整的Web框架,适合大型项目开发。

安装Django

pip install django

创建Django项目

# 创建项目
django-admin startproject mysite

# 项目结构
mysite/
    manage.py
    mysite/
        __init__.py
        settings.py
        urls.py
        wsgi.py

# 运行开发服务器
cd mysite
python manage.py runserver

# 访问: http://localhost:8000

创建应用

# 创建应用
python manage.py startapp blog

# 在settings.py中注册应用
INSTALLED_APPS = [
    'django.contrib.admin',
    'django.contrib.auth',
    'django.contrib.contenttypes',
    'django.contrib.sessions',
    'django.contrib.messages',
    'django.contrib.staticfiles',
    'blog',  # 添加应用
]

定义模型

# blog/models.py
from django.db import models

class Post(models.Model):
    title = models.CharField(max_length=200)
    content = models.TextField()
    created_at = models.DateTimeField(auto_now_add=True)
    updated_at = models.DateTimeField(auto_now=True)

    def __str__(self):
        return self.title

# 创建数据库表
python manage.py makemigrations
python manage.py migrate

视图和URL

# blog/views.py
from django.shortcuts import render
from django.http import HttpResponse
from .models import Post

def index(request):
    posts = Post.objects.all()
    return render(request, 'blog/index.html', {'posts': posts})

def detail(request, post_id):
    post = Post.objects.get(id=post_id)
    return render(request, 'blog/detail.html', {'post': post})

# blog/urls.py
from django.urls import path
from . import views

urlpatterns = [
    path('', views.index, name='index'),
    path('/', views.detail, name='detail'),
]

# mysite/urls.py
from django.contrib import admin
from django.urls import path, include

urlpatterns = [
    path('admin/', admin.site.urls),
    path('blog/', include('blog.urls')),
]

HTTP请求处理

使用requests库

import requests

# GET请求
response = requests.get('https://api.example.com/users')
print(response.status_code)
print(response.json())

# POST请求
data = {'name': '张三', 'age': 25}
response = requests.post('https://api.example.com/users', json=data)
print(response.json())

# 带参数的GET请求
params = {'page': 1, 'limit': 10}
response = requests.get('https://api.example.com/users', params=params)

# 带请求头
headers = {'Authorization': 'Bearer token123'}
response = requests.get('https://api.example.com/protected', headers=headers)

# 处理异常
try:
    response = requests.get('https://api.example.com/data', timeout=5)
    response.raise_for_status()
    data = response.json()
except requests.exceptions.RequestException as e:
    print(f"请求失败: {e}")

RESTful API设计

REST是一种Web服务架构风格,使用HTTP方法操作资源。

Flask-RESTful示例

from flask import Flask
from flask_restful import Api, Resource, reqparse

app = Flask(__name__)
api = Api(app)

users = {}
user_id_counter = 1

class UserList(Resource):
    def get(self):
        return list(users.values())

    def post(self):
        global user_id_counter
        parser = reqparse.RequestParser()
        parser.add_argument('name', required=True)
        parser.add_argument('age', type=int, required=True)
        args = parser.parse_args()

        user = {
            'id': user_id_counter,
            'name': args['name'],
            'age': args['age']
        }
        users[user_id_counter] = user
        user_id_counter += 1
        return user, 201

class User(Resource):
    def get(self, user_id):
        return users.get(user_id, {'error': '用户不存在'}), 200 if user_id in users else 404

    def put(self, user_id):
        parser = reqparse.RequestParser()
        parser.add_argument('name')
        parser.add_argument('age', type=int)
        args = parser.parse_args()

        if user_id in users:
            users[user_id].update(args)
            return users[user_id]
        return {'error': '用户不存在'}, 404

    def delete(self, user_id):
        if user_id in users:
            del users[user_id]
            return '', 204
        return {'error': '用户不存在'}, 404

api.add_resource(UserList, '/api/users')
api.add_resource(User, '/api/users/')

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

数据库操作

SQLite with Flask

import sqlite3
from flask import Flask, g

app = Flask(__name__)
DATABASE = 'database.db'

def get_db():
    db = getattr(g, '_database', None)
    if db is None:
        db = g._database = sqlite3.connect(DATABASE)
        db.row_factory = sqlite3.Row
    return db

@app.teardown_appcontext
def close_connection(exception):
    db = getattr(g, '_database', None)
    if db is not None:
        db.close()

@app.route('/users')
def get_users():
    db = get_db()
    cursor = db.execute('SELECT * FROM users')
    users = [dict(row) for row in cursor.fetchall()]
    return jsonify(users)

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

练习

  1. 创建一个Flask应用,实现用户注册和登录功能
  2. 编写RESTful API,实现图书管理系统(增删改查)
  3. 使用requests库调用公开API并处理返回数据
  4. 创建一个简单的博客系统,包含文章列表和详情页
练习答案:
# 练习1:用户注册登录
from flask import Flask, request, jsonify, session

app = Flask(__name__)
app.secret_key = 'your-secret-key'

users = {}

@app.route('/register', methods=['POST'])
def register():
    data = request.get_json()
    username = data['username']
    password = data['password']

    if username in users:
        return jsonify({'error': '用户已存在'}), 400

    users[username] = password
    return jsonify({'message': '注册成功'}), 201

@app.route('/login', methods=['POST'])
def login():
    data = request.get_json()
    username = data['username']
    password = data['password']

    if username in users and users[username] == password:
        session['username'] = username
        return jsonify({'message': '登录成功'})

    return jsonify({'error': '用户名或密码错误'}), 401

# 练习2:图书管理API
from flask import Flask
from flask_restful import Api, Resource

app = Flask(__name__)
api = Api(app)

books = []
book_id = 1

class BookList(Resource):
    def get(self):
        return books

    def post(self):
        global book_id
        data = request.get_json()
        book = {
            'id': book_id,
            'title': data['title'],
            'author': data['author']
        }
        books.append(book)
        book_id += 1
        return book, 201

api.add_resource(BookList, '/api/books')

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