Fonctionnalité de favoris et gestion d'administration
Dans ce chapitre, vous apprendrez comment implémenter une fonctionnalité de favoris en utilisant une relation plusieurs-à-plusieurs, et utiliser sqladmin pour mettre en place un back-end d'administration.
Conception de relation plusieurs-à-plusieurs
Exemple
from sqlalchemy import Table
# Table d'association : table intermédiaire plusieurs-à-plusieurs entre User et Post
favorites = Table(
"favorites",
Base.metadata,
Column("user_id", Integer, ForeignKey("users.id"), primary_key=True),
Column("post_id", Integer, ForeignKey("posts.id"), primary_key=True),
Column("created_at", DateTime, default=datetime.utcnow)
)
Exécuter la migration :
(venv) $ alembic revision --autogenerate -m "新增收藏关联表" (venv) $ alembic upgrade head
Routes d'ajout et de retrait des favoris
Exemple
from fastapi import APIRouter, Depends, HTTPException, Demande
from sqlalchemy.orm import Session
from database import get_db
from models import Post, favorites
from routers.users import get_current_user
from fastapi.templating import Jinja2Templates
router = APIRouter(prefix="/favorites", tags=["Favorites"])
templates = Jinja2Templates(directory="templates")
@router.post("/toggle/{post_id}")
def toggle_favorite(
post_id: int,
request: Request,
db: Session = Depends(get_db),
current_user = Depends(get_current_user) # Connexion requise
):
"""Basculer le statut de favori"""
post = db.query(Post).filter(Post.id == post_id).first()
if not post:
raise HTTPException(status_code=404, detail=“L'article n'existe pas”)
# Vérifier si déjà en favori
is_faved = db.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.execute(
favorites.delete().where(
(favorites.c.user_id == current_user.id) &
(favorites.c.post_id == post.id)
)
)
db.commit()
else:
# Ajouter aux favoris
db.execute(
favorites.insert().values(user_id=current_user.id, post_id=post.id)
)
db.commit()
from fastapi.responses import RedirectResponse
return RedirectResponse(url=request.headers.get("referer", "/"), status_code=303)
@router.get("/", name="favorites_list")
def favorites_list(
request: Request,
db: Session = Depends(get_db),
current_user = Depends(get_current_user)
):
"""Ma liste de favoris"""
faved_posts = db.query(Post).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 templates.TemplateResponse("favorites.html", {
"request": request,
"posts": faved_posts
})
Ajouter un bouton Favori sur la page de détail
Exemple
<div class="post-header">
<h1>{{ post.title }}</h1>
<form method="post" action="/favorites/toggle/{{ post.id }}">
<button type="submit" class="fav-btn">♡ Favori</bouton>
</forme>
</div>
sqladmin — Gestion de l'administration
sqladminC'est l'extension d'administration backend de l'écosystème FastAPI qui est l'équivalent de Django Admin.
Il est conçu spécifiquement pour SQLAlchemy et s'intègre parfaitement à FastAPI.
(venv) $ pip install sqladmin
Exemple
from sqladmin import Admin, ModelView
from database import engine
from models import Post, Category, User
class PostAdmin(ModelView, model=Post):
column_list = [Post.id, Post.title, Post.category, Post.created_at]
column_searchable_list = [Post.title, Post.summary]
column_sortable_list = [Post.created_at, Post.title]
form_columns = [Post.title, Post.slug, Post.summary, Post.content, Post.category_id]
class CategoryAdmin(ModelView, model=Category):
column_list = [Category.id, Category.name, Category.slug]
form_columns = [Category.name, Category.slug]
class UserAdmin(ModelView, model=User):
column_list = [User.id, User.username, User.email]
column_searchable_list = [User.username, User.email]
# Ne pas afficher le champ mot de passe (pour des raisons de sécurité)
form_excluded_columns = [User.hashed_password]
# Créer une instance Admin et la lier à l'application FastAPI
admin = Admin(app, engine, title=EXEMPLE Admin du blog)
admin.add_view(PostAdmin)
admin.add_view(CategoryAdmin)
admin.add_view(UserAdmin)
Visitez /admin pour accéder à l'interface d'administration.
sqladmin vs Flask-Admin vs Django Admin
| Fonctionnalités | Django Admin | Flask-Admin | sqladmin |
|---|---|---|---|
| Méthode d'inscription | admin.site.register() | admin.add_view(ModelView()) | Admin + add_view |
| Prise en charge de l'ORM | ORM Django | SQLAlchemy / MongoEngine | SQLAlchemy (uniquement) |
| Prise en charge de l'authentification | Intégré | Nécessite une intégration manuelle | authentication_backend intégré |
| Prise en charge de l'asynchrone | Non pris en charge | Non pris en charge | asynchrone natif |
sqladmin est accessible sans connexion par défaut. Il doit être configuré pour les environnements de production.
authentication_backendPour ajouter une protection, consultez la documentation officielle de sqladmin.
Résumé du chapitre
Dans ce chapitre, vous avez implémenté deux fonctionnalités importantes : utiliser une table d'association Table pour implémenter la relation plusieurs-à-plusieurs des favoris ; et utiliser sqladmin pour mettre rapidement en place un système de gestion d'administration backend.
Le blog dispose désormais de fonctionnalités complètes d'interaction utilisateur (inscription, connexion, favoris) et de fonctions de gestion (backend d'administration).
autres extensions