各位好,今天咱们来聊聊Python Web开发的三驾马车:Django、Flask 和 FastAPI。这仨框架,就像武林中的三大门派,各有各的招式和特点,咱们今天就来好好扒一扒它们的架构,看看谁更适合你的项目。
(开场白结束,直接进入正题)
一、Django:全能选手,开箱即用
Django,江湖人称“重型武器”,或者“瑞士军刀”。它最大的特点就是“啥都有”,你需要的,它基本都给你准备好了。
1. 架构:MVT (Model-View-Template)
Django 采用的是 MVT 架构,乍一看有点像 MVC (Model-View-Controller),但实际上还是有些区别的。
-
Model (模型): 负责数据管理,定义数据结构,处理数据库交互。简单来说,就是告诉 Django,你的数据长啥样,怎么存,怎么取。
# models.py from django.db import models class Article(models.Model): title = models.CharField(max_length=200) content = models.TextField() pub_date = models.DateTimeField('date published') def __str__(self): return self.title
这段代码定义了一个
Article
模型,包含了标题、内容和发布日期。 Django 会根据这个模型自动创建数据库表。 -
View (视图): 负责处理用户请求,调用 Model 获取数据,并将数据传递给 Template 进行渲染。 视图就像一个中间人,连接数据和展示。
# views.py from django.shortcuts import render from .models import Article def article_list(request): articles = Article.objects.all() return render(request, 'article_list.html', {'articles': articles})
这个
article_list
视图从数据库获取所有文章,并将它们传递给article_list.html
模板进行渲染。 -
Template (模板): 负责展示数据,将 Model 传递过来的数据渲染成 HTML 页面。 模板就是前端的“皮囊”,负责美化数据。
<!-- article_list.html --> <!DOCTYPE html> <html> <head> <title>Article List</title> </head> <body> <h1>Article List</h1> <ul> {% for article in articles %} <li>{{ article.title }} - {{ article.pub_date }}</li> {% endfor %} </ul> </body> </html>
这个模板循环遍历
articles
列表,并将每篇文章的标题和发布日期显示在页面上。注意: 在MVT架构中,Django框架本身充当了Controller的角色,处理URL路由,请求分发等。所以开发者主要关注Model、View和Template的编写即可。
2. 特点:
-
功能齐全: 自带 ORM、模板引擎、表单处理、用户认证、安全机制等,几乎所有你需要的功能,Django 都已经帮你实现了。 就像一个装备精良的战士,直接可以上战场。
-
开发效率高: 由于功能齐全,很多重复性的工作都可以交给 Django 自动完成,大大提高了开发效率。
-
安全性高: Django 内置了很多安全机制,例如 CSRF 保护、XSS 保护等,可以有效防止常见的 Web 攻击。
-
社区庞大: Django 拥有庞大的社区,遇到问题可以很容易找到解决方案。
-
学习曲线陡峭: Django 的功能太多了,需要学习的东西也比较多,上手难度相对较高。
-
重量级: 对于一些小型项目,Django 显得有些笨重。
3. 适用场景:
- 大型 Web 应用
- 需要快速开发的项目
- 对安全性要求高的项目
4. 示例代码:一个简单的博客示例
除了上面的基本代码,咱们再来个更完整的例子,一个简单的博客,包含文章列表和文章详情。
-
models.py:
from django.db import models class Article(models.Model): title = models.CharField(max_length=200) content = models.TextField() pub_date = models.DateTimeField('date published') author = models.CharField(max_length=100, default="Unknown") # 添加作者字段 def __str__(self): return self.title
-
views.py:
from django.shortcuts import render, get_object_or_404 from .models import Article def article_list(request): articles = Article.objects.all().order_by('-pub_date') # 按发布日期倒序排序 return render(request, 'article_list.html', {'articles': articles}) def article_detail(request, article_id): article = get_object_or_404(Article, pk=article_id) # 获取指定ID的文章,如果不存在则返回404 return render(request, 'article_detail.html', {'article': article})
-
urls.py (项目级别的 urls.py 需要包含 app 的 urls.py):
from django.contrib import admin from django.urls import path, include urlpatterns = [ path('admin/', admin.site.urls), path('blog/', include('blog.urls')), # 包含 blog 应用的 urls.py ]
-
urls.py (blog 应用级别的 urls.py,需要自己创建):
from django.urls import path from . import views urlpatterns = [ path('', views.article_list, name='article_list'), # 文章列表 path('<int:article_id>/', views.article_detail, name='article_detail'), # 文章详情 ]
-
templates/article_list.html:
<!DOCTYPE html> <html> <head> <title>Article List</title> </head> <body> <h1>Article List</h1> <ul> {% for article in articles %} <li> <a href="{% url 'article_detail' article.id %}">{{ article.title }}</a> - {{ article.pub_date }} - By {{ article.author }} </li> {% endfor %} </ul> </body> </html>
-
templates/article_detail.html:
<!DOCTYPE html> <html> <head> <title>{{ article.title }}</title> </head> <body> <h1>{{ article.title }}</h1> <p>Published on: {{ article.pub_date }}</p> <p>By: {{ article.author }}</p> <p>{{ article.content }}</p> <a href="{% url 'article_list' %}">Back to Article List</a> </body> </html>
这个例子展示了 Django 的基本用法,包括定义模型、创建视图、编写模板、配置 URL。
二、Flask:灵活自由,微框架之王
Flask,江湖人称“轻量级选手”,或者“积木”。它最大的特点就是“小而美”,核心功能非常精简,但可以通过扩展来实现各种功能。
1. 架构:Werkzeug + Jinja2
Flask 本身并没有强制的架构,但通常会采用 Werkzeug (WSGI 工具包) 和 Jinja2 (模板引擎) 来构建 Web 应用。
-
Werkzeug: 负责处理 HTTP 请求和响应,提供路由、调试器等基础功能。 它就像 Flask 的骨架,支撑着整个应用。
-
Jinja2: 负责模板渲染,将数据渲染成 HTML 页面。 和 Django 的模板引擎类似,但更加灵活。
2. 特点:
-
轻量级: 核心功能非常精简,易于学习和使用。
-
灵活性高: 可以根据自己的需求选择不同的扩展,定制自己的 Web 应用。 就像一个乐高积木,可以搭建出各种各样的模型。
-
自由度高: 没有强制的目录结构和代码风格,可以自由发挥。
-
学习曲线平缓: 上手难度较低,适合初学者。
-
需要手动集成: 很多功能需要手动集成,例如 ORM、表单处理等。
-
安全性需要自己把控: 需要自己处理安全问题,例如 CSRF 保护、XSS 保护等。
3. 适用场景:
- 小型 Web 应用
- API 开发
- 需要高度定制的项目
4. 示例代码:一个简单的 Hello World
from flask import Flask
app = Flask(__name__)
@app.route('/')
def hello_world():
return 'Hello, World!'
if __name__ == '__main__':
app.run(debug=True)
这段代码定义了一个 Flask 应用,当访问根路径时,会返回 "Hello, World!"。
5. 示例代码:一个简单的博客示例
为了更清晰地展示 Flask 的用法,我们再来一个简单的博客示例。
-
app.py:
from flask import Flask, render_template, request, redirect, url_for from flask_sqlalchemy import SQLAlchemy from datetime import datetime app = Flask(__name__) app.config['SQLALCHEMY_DATABASE_URI'] = 'sqlite:///blog.db' # 使用 SQLite 数据库 db = SQLAlchemy(app) class Article(db.Model): id = db.Column(db.Integer, primary_key=True) title = db.Column(db.String(200), nullable=False) content = db.Column(db.Text, nullable=False) pub_date = db.Column(db.DateTime, default=datetime.utcnow) author = db.Column(db.String(100), default="Unknown") def __repr__(self): return '<Article %r>' % self.title @app.route('/') def index(): articles = Article.query.order_by(Article.pub_date.desc()).all() return render_template('index.html', articles=articles) @app.route('/article/<int:id>') def article(id): article = Article.query.get_or_404(id) return render_template('article.html', article=article) @app.route('/create', methods=['GET', 'POST']) def create(): if request.method == 'POST': title = request.form['title'] content = request.form['content'] author = request.form['author'] new_article = Article(title=title, content=content, author=author) try: db.session.add(new_article) db.session.commit() return redirect('/') except: return 'There was an issue adding your article' else: return render_template('create.html') if __name__ == "__main__": with app.app_context(): db.create_all() # Create database tables app.run(debug=True)
-
templates/index.html:
<!DOCTYPE html> <html> <head> <title>Flask Blog</title> </head> <body> <h1>Flask Blog</h1> <a href="{{ url_for('create') }}">Create New Article</a> <ul> {% for article in articles %} <li> <a href="{{ url_for('article', id=article.id) }}">{{ article.title }}</a> - {{ article.pub_date }} - By {{ article.author }} </li> {% endfor %} </ul> </body> </html>
-
templates/article.html:
<!DOCTYPE html> <html> <head> <title>{{ article.title }}</title> </head> <body> <h1>{{ article.title }}</h1> <p>Published on: {{ article.pub_date }}</p> <p>By: {{ article.author }}</p> <p>{{ article.content }}</p> <a href="{{ url_for('index') }}">Back to Home</a> </body> </html>
-
templates/create.html:
<!DOCTYPE html> <html> <head> <title>Create New Article</title> </head> <body> <h1>Create New Article</h1> <form action="{{ url_for('create') }}" method="POST"> <label for="title">Title:</label><br> <input type="text" id="title" name="title"><br><br> <label for="content">Content:</label><br> <textarea id="content" name="content" rows="4" cols="50"></textarea><br><br> <label for="author">Author:</label><br> <input type="text" id="author" name="author"><br><br> <input type="submit" value="Submit"> </form> </body> </html>
这个例子使用了 Flask-SQLAlchemy 扩展来操作数据库,展示了 Flask 的基本用法,包括定义路由、渲染模板、处理表单。
三、FastAPI:高性能,异步之选
FastAPI,江湖人称“速度之王”,或者“新贵”。它最大的特点就是“快”,基于 ASGI (Asynchronous Server Gateway Interface) 构建,可以处理大量的并发请求。
1. 架构:基于 ASGI
FastAPI 基于 ASGI 构建,这意味着它可以利用异步特性来提高性能。 传统的 WSGI 应用是同步的,而 ASGI 应用是异步的,可以并发处理多个请求。
2. 特点:
-
高性能: 基于 ASGI 构建,可以处理大量的并发请求。 适合对性能要求高的项目。
-
自动数据验证: 基于 Pydantic 进行数据验证,可以自动验证请求和响应的数据类型。 减少了手动验证的工作量。
-
自动 API 文档: 可以自动生成 OpenAPI (Swagger UI) 和 ReDoc API 文档。 方便 API 的使用和测试。
-
易于使用: 语法简洁,易于学习和使用。
-
异步编程: 需要掌握异步编程的概念,上手难度相对较高。
-
生态系统相对较小: 相比 Django 和 Flask,FastAPI 的生态系统还不够完善。
3. 适用场景:
- API 开发
- 微服务
- 需要高性能的项目
4. 示例代码:一个简单的 Hello World
from fastapi import FastAPI
app = FastAPI()
@app.get("/")
async def read_root():
return {"Hello": "World"}
这段代码定义了一个 FastAPI 应用,当访问根路径时,会返回一个 JSON 对象。
5. 示例代码:一个简单的带参数的 API
from fastapi import FastAPI
app = FastAPI()
@app.get("/items/{item_id}")
async def read_item(item_id: int, q: str = None):
return {"item_id": item_id, "q": q}
这段代码定义了一个 API,可以接收一个 item_id
参数和一个可选的 q
参数。 FastAPI 会自动验证 item_id
是否为整数。
6. 示例代码:一个简单的博客 API
为了更清晰地展示 FastAPI 的用法,我们再来一个简单的博客 API 示例。
-
main.py:
from typing import List from fastapi import FastAPI, HTTPException from pydantic import BaseModel from datetime import datetime app = FastAPI() class Article(BaseModel): id: int = None title: str content: str pub_date: datetime = None author: str = "Unknown" articles = [] article_id_counter = 1 @app.get("/articles", response_model=List[Article]) async def list_articles(): return articles @app.post("/articles", response_model=Article) async def create_article(article: Article): global article_id_counter article.id = article_id_counter article.pub_date = datetime.utcnow() articles.append(article) article_id_counter += 1 return article @app.get("/articles/{article_id}", response_model=Article) async def get_article(article_id: int): for article in articles: if article.id == article_id: return article raise HTTPException(status_code=404, detail="Article not found") @app.put("/articles/{article_id}", response_model=Article) async def update_article(article_id: int, updated_article: Article): for i, article in enumerate(articles): if article.id == article_id: updated_article.id = article_id updated_article.pub_date = article.pub_date # 保留原发布日期 articles[i] = updated_article return updated_article raise HTTPException(status_code=404, detail="Article not found") @app.delete("/articles/{article_id}") async def delete_article(article_id: int): for i, article in enumerate(articles): if article.id == article_id: del articles[i] return {"message": "Article deleted"} raise HTTPException(status_code=404, detail="Article not found")
这个例子展示了 FastAPI 的基本用法,包括定义数据模型、创建 API 接口、处理 HTTP 请求。 你可以通过访问 http://127.0.0.1:8000/docs
或 http://127.0.0.1:8000/redoc
来查看自动生成的 API 文档。
四、总结:选择适合你的框架
好,说了这么多,咱们来总结一下这三个框架的特点,方便大家选择。
特性 | Django | Flask | FastAPI |
---|---|---|---|
架构 | MVT | Werkzeug + Jinja2 | 基于 ASGI |
特点 | 功能齐全,开发效率高 | 轻量级,灵活性高 | 高性能,自动 API 文档 |
学习曲线 | 陡峭 | 平缓 | 适中 |
适用场景 | 大型 Web 应用 | 小型 Web 应用,API 开发 | API 开发,微服务 |
是否自带ORM | 是 | 否(需要集成) | 否(需要集成) |
是否自带模板引擎 | 是 | 是(Jinja2) | 否(需要集成,但常用) |
异步支持 | 较弱(但已在改进) | 否 | 强大 |
选择建议:
- 如果你需要快速开发一个大型 Web 应用,并且对安全性要求很高,那么 Django 是一个不错的选择。
- 如果你需要开发一个小型 Web 应用或者 API,并且希望有更高的灵活性,那么 Flask 是一个不错的选择。
- 如果你需要开发一个高性能的 API 或者微服务,那么 FastAPI 是一个不错的选择。
当然,选择框架并不是绝对的,最终还是要根据你的项目需求和个人喜好来决定。 重要的是理解每个框架的优缺点,才能做出最合适的选择。
今天的讲座就到这里,希望对大家有所帮助! 祝大家编程愉快!