View-Funktionen — Artikelliste und Detailseiten rendern
In diesem Kapitel lernst du, Daten mit View-Funktionen aus der Datenbank abzufragen, die Startseite und Detailseiten zu rendern und Routen mit Blueprint aufzuteilen.
Die Aufgaben der View-Funktionen
Flask-View-Funktionen haben die gleichen Aufgaben wie Django:Anfrage empfangen → Daten abfragen → Template rendern。
Beispiel
from flask import Flask, render_template
from models import Post, Category
@app.route("/")
def index():
"""Blog-Startseite: zeigt alle Artikel an"""
posts = Post.query.order_by(Post.created_at.desc()).all()
categories = Category.query.all()
return render_template('index.html', posts=posts, categories=categories)
Pfadparameter und Query-Parameter
| Parametertyp | URL-Beispiel | Wie Views erhalten werden |
|---|---|---|
| Pfadparameter | /post/3 | In Routen, <type:variable_name> → Funktionsparameter |
| Query-Parameter | /?category=python | request.args.get('key') |
Flask-Routen unterstützen mehrere Typkonverter:<int:id>(integer),<string:slug>(Standard, enthält kein /),<path:path>(enthält /),<float:price>usw.
Artikelseite
Beispiel
from flask import abort
@app.route("/post/<int:post_id>")
def post_detail(post_id):
"""Artikeldetailseite"""
# get_or_404 ist äquivalent zu: Post.query.get(post_id) or abort(404)
post = Post.query.get_or_404(post_id,
description=f'Artikel #{post_id} existiert nicht')
return render_template('post_detail.html', post=post)
Benutzerdefinierte 404-Fehlerseite
Beispiel
def not_found(error):
return render_template('404.html'), 404
Kategoriefilterung
Beispiel
from flask import request
@app.route("/")
def index():
category_slug = request.args.get('category', '')
keyword = request.args.get('q', '') # Suchbegriff (implementiert in Kapitel 6)
posts_query = Post.query.order_by(Post.created_at.desc())
# Nach Kategorie filtern
if category_slug:
posts_query = posts_query.join(Category).filter(Category.slug == category_slug)
posts = posts_query.all()
categories = Category.query.all()
return render_template('index.html',
posts=posts, categories=categories,
category_slug=category_slug, keyword=keyword)
request.argsist ein unveränderliches MultiDict, das zum Auslesen von URL-Abfrageparametern verwendet wird. Verwenden Sie.get('key', '默认值')Sicherer Abruf: Gibt einen Standardwert zurück, wenn der Parameter nicht existiert, anstatt einen Fehler auszulösen.
Blueprint — Routen aufteilen
Wenn View-Funktionen zunehmen, wird das Stapeln aller in app.py unüberschaubar.
BlueprintEs ist Flasks Schema zur Routengruppierung: Views nach funktionalen Modulen aufteilen und über app.register_blueprint() registrieren.
app/ ├── blueprints/ │ ├── __init__.py │ ├── main.py # 首页、关于、搜索 │ └── posts.py # 文章列表、详情 ├── templates/ ├── models.py └── __init__.py
Beispiel
from flask import Blueprint, render_template, request
from app.models import Post, Category
# Blueprint('blueprint_name', __name__, url_prefix='/')
main_bp = Blueprint('main', __name__)
@main_bp.route("/")
def index():
"""Blog-Startseite"""
category_slug = request.args.get('category', '')
posts_query = Post.query.order_by(Post.created_at.desc())
if category_slug:
posts_query = posts_query.join(Category).filter(Category.slug == category_slug)
return render_template('index.html',
posts=posts_query.all(),
categories=Category.query.all(),
category_slug=category_slug)
Beispiel
from flask import Blueprint, render_template, abort
from app.models import Post
posts_bp = Blueprint('posts', __name__)
@posts_bp.route("/post/<int:post_id>")
def post_detail(post_id):
post = Post.query.get_or_404(post_id)
return render_template('post_detail.html', post=post)
Registrieren Sie den Blueprint am Einstiegspunkt der Anwendung:
Beispiel
from flask import Flask
from app.blueprints.main import main_bp
from app.blueprints.posts import posts_bp
app = Flask(__name__)
# Blueprints registrieren: Alle View-Funktionen der Blueprints werden in derselben Anwendung zusammengeführt
app.register_blueprint(main_bp)
app.register_blueprint(posts_bp)
Ein Blueprint kann angeben
url_prefix(wie z. B.url_prefix='/blog'), dann wird allen Routen innerhalb des Blueprints automatisch dieses Präfix hinzugefügt. Ein Blueprint kann auch eigene Verzeichnisse für Templates und statische Dateien haben.
Templates für die Startseite und die Detailseite erstellen
index.html
Beispiel
{% extends 'base.html' %}
{% block title %}EXAMPLE Blog - Startseite{% endblock %}
{% block content %}
<h2 class="section-title">Neueste Artikel</h2>
<!-- Kategoriefilter-Navigation -->
<div class="category-bar">
<a href="{{ url_for('main.index') }}"
class="{% if not category_slug %}active{% endif %}">Alle</a>
{% for cat in categories %}
<a href="{{ url_for('main.index', category=cat.slug) }}"
class="{% if category_slug == cat.slug %}active{% endif %}">
{{ cat.name }}
</a>
{% endfor %}
</div>
{% if posts %}
<div class="article-grid">
{% for post in posts %}
<a href="{{ url_for('posts.post_detail', post_id=post.id) }}" class="card-link">
<div class="article-card">
<div class="card-content">
<span class="card-category">{{ post.category.name }}</span>
<h3>{{ post.title }}</h3>
<p>{{ post.summary|truncate(80) }}</p>
<span class="card-date">{{ post.created_at.strftime('%Y-%m-%d') }}</span>
</div>
</div>
</a>
{% endfor %}
</div>
{% else %}
<p class="empty-tip">Noch keine Artikel in dieser Kategorie.</p>
{% endif %}
{% endblock %}
Bei Verwendung einer Blueprint-Ansicht in url_for() lautet das Format
url_for('蓝图名.函数名'), wie zum Beispielurl_for('posts.post_detail', post_id=3). Beachten Sie den Unterschied zu Djangos{% url %}Tag-Vergleich: Flask verwendet{{ url_for() }}, können in Python-Ausdrücke verschachtelt werden, um mehr Flexibilität zu bieten.
Kapitelzusammenfassung
In diesem Kapitel hast du Flask-Views und die Routenorganisation gemeistert: Post.query zum Abfragen von Daten, Pfadparameter <int:post_id> und Query-Parameter request.args, get_or_404 für sichere Abfragen, abort(404) und benutzerdefinierte Fehlerseiten sowie Blueprint zum Aufteilen von Routen nach Modulen.
Der Blog hat jetzt drei vollständige Seiten: die Artikelliste auf der Startseite, die Kategoriefilterung und Detailseiten.
Weitere Erweiterungen