Fonctionnalité de favoris et gestion du backend
Dans ce chapitre, vous apprendrez à implémenter une fonctionnalité de signets en utilisant des relations plusieurs-à-plusieurs et à construire rapidement une interface d'administration backend avec Flask-Admin.
Conception de relation plusieurs-à-plusieurs
Exigences pour la fonctionnalité de favoris :Un utilisateur peut ajouter plusieurs publications aux favoris, et une publication peut être ajoutée aux favoris par plusieurs utilisateurs.。
Dans SQLAlchemy, les relations plusieurs-à-plusieurs sont gérées viaTable d'associationImplémentation.
Exemple
from datetime import datetime
# Table d'association : pas besoin de la définir comme classe de modèle, créez-la directement avec db.Table
favorites = db.Table('favorites',
db.Column('user_id', db.Integer, db.ForeignKey('users.id'), primary_key=True),
db.Column('post_id', db.Integer, db.ForeignKey('posts.id'), primary_key=True),
db.Column('created_at', db.DateTime, default=datetime.utcnow)
)
class Post(db.Model):
__tablename__ = 'posts'
# ... les champs existants restent inchangés ...
Ensuite, exécutez la migration :
(venv) $ flask db migrate -m "新增收藏关联表" (venv) $ flask db upgrade
Vues d'ajout et de retrait des favoris
Exemple
from flask import Blueprint, render_template, redirect, url_for, request, flash
from flask_login import login_required, current_user
from app.models import Post, db, favorites
user_bp = Blueprint('user', __name__)
@user_bp.route("/favorite/<int:post_id>", methods=['POST'])
@login_required
def toggle_favorite(post_id):
"""Basculer le statut de favori"""
post = Post.query.get_or_404(post_id)
# Vérifier si déjà ajouté aux favoris : interroger la table d'association pour cette combinaison utilisateur-publication
is_faved = db.session.query(favorites).filter(
favorites.c.user_id == current_user.id,
favorites.c.post_id == post.id
).first() is not None
if is_faved:
# Retirer des favoris
db.session.execute(
favorites.delete().where(
(favorites.c.user_id == current_user.id) &
(favorites.c.post_id == post.id)
)
)
db.session.commit()
flash(f'Retiré des favoris "{post.title}"', 'info')
else:
# Ajouter aux favoris
db.session.execute(
favorites.insert().values(user_id=current_user.id, post_id=post.id)
)
db.session.commit()
flash(f'Ajouté aux favoris : "{post.title}"', 'success')
return redirect(request.referrer or url_for('main.index'))
@user_bp.route("/favorites")
@login_required
def favorites_list():
"""Liste des favoris de l'utilisateur actuel"""
# Interroger les articles mis en favori par les utilisateurs via la table d'association
faved_posts = Post.query.join(
favorites, (favorites.c.post_id == Post.id)
).filter(
favorites.c.user_id == current_user.id
).order_by(favorites.c.created_at.desc()).all()
return render_template('favorites.html', posts=faved_posts)
Enregistrer le Blueprint dans app.py
Exemple
app.register_blueprint(user_bp)
Ajouter des boutons de favori sur la page de détail et la page de liste
Exemple
{% if current_user.is_authenticated %}
<form method="post" action="{{ url_for('user.toggle_favorite', post_id=post.id) }}">
<button type="submit" class="fav-btn">
{% set is_faved = false %}
{# Vérifier si l'utilisateur actuel figure dans la liste des utilisateurs qui ont mis l'article en favori #}
♡ Favori
</button>
</forme>
{% endif %}
Les opérations sur les favoris utilisent des requêtes POST (soumission de formulaire), et non des liens GET. Les requêtes GET ne doivent pas produire d'effets de bord (modifier la base de données) ; c'est un principe fondamental du développement web.
Flask-Admin — Gestion du backend
Flask-AdminC'est l'extension de l'écosystème Flask qui est équivalente à Django Admin.
Après configuration, vous pouvez gérer les articles et les catégories dans le navigateur.
(venv) $ pip install flask-admin
Exemple
from flask_admin import Admin
from flask_admin.contrib.sqla import ModelView
from app.models import Post, Category, Utilisateur
# ModelView personnalisé : contrôler quels champs sont affichés dans le backend d'administration
class PostAdmin(ModelView):
column_list = ['title', 'category', 'created_at', 'updated_at']
column_searchable_list = ['title', 'summary']
column_filters = ['category', 'created_at']
form_columns = ['title', 'slug', 'summary', 'content', 'category']
class CategoryAdmin(ModelView):
column_list = ['name', 'slug']
form_columns = ['name', 'slug']
# Créer une instance d'Admin
admin = Admin(app, name='Admin du blog EXEMPLE', template_mode='bootstrap4')
admin.add_view(PostAdmin(Post, db.session, name='Articles'))
admin.add_view(CategoryAdmin(Category, db.session, name='Catégories'))
admin.add_view(ModelView(User, db.session, name='Utilisateurs'))
Démarrez le serveur et visitez/admin, et vous pouvez accéder à l'interface d'administration.
Flask-Admin vs Django Admin
| Fonctionnalités | Flask-Admin | Django Admin |
|---|---|---|
| Méthode d'intégration | Extension tierce, nécessite pip install | Intégré à django.contrib.admin |
| Enregistrer les modèles | admin.add_view(ModelView(Model, session)) | admin.site.register(Model) |
| Champs de liste | column_list | list_display |
| Rechercher | column_searchable_list | search_fields |
| Filter | column_filters | list_filter |
| Authentification requise | Non intégré (nécessite d'ajouter manuellement @login_required) | Permissions d'administrateur intégrées |
Flask-Admin ne nécessite pas de connexion pour y accéder par défaut ; il doit être combiné avec Flask-Login pour le contrôle des permissions. Une façon simple est d'ajouter
@login_required, ou remplacer la méthode de ModelViewis_accessiblepour vérifier les permissions d'administrateur.
Résumé du chapitre
Dans ce chapitre, vous avez implémenté deux fonctionnalités importantes : l'utilisation de la table d'association db.Table + des opérations db.session.execute pour implémenter la relation plusieurs-à-plusieurs pour les signets ; et l'utilisation de Flask-Admin pour construire rapidement un système d'administration back-end.
Maintenant, les fonctionnalités interactives du blog (utilisateurs, signets) et les fonctionnalités de gestion (back-end) sont toutes complètes.
autres extensions