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

# Dateipfad: app.py
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

ParametertypURL-BeispielWie Views erhalten werden
Pfadparameter/post/3In Routen, <type:variable_name> → Funktionsparameter
Query-Parameter/?category=pythonrequest.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

# Dateipfad: app.py append
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

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

Kategoriefilterung

Beispiel

# Dateipfad: Index-Ansicht in app.py refaktorieren
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

# Dateipfad: app/blueprints/main.py
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

# Dateipfad: app/blueprints/posts.py
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

# Dateipfad: app.py
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 angebenurl_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

<!-- Dateipfad: app/templates/index.html -->
{% 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 Formaturl_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